最近在C++項(xiàng)目中用異常竹捉,有一些總結(jié)尚骄,希望能得到大家斧正。
C++之父Bjarne Stroustrup在《The C++ Programming Language》中講到:
一個(gè)庫(kù)的作者可以檢測(cè)出發(fā)生了運(yùn)行時(shí)錯(cuò)誤状蜗,但一般不知道怎樣去處理它們(因?yàn)楹陀脩艟唧w的應(yīng)用有關(guān))鹉动;另一方面,庫(kù)的用戶知道怎樣處理這些錯(cuò)誤眶根,但卻無(wú)法檢查它們何時(shí)發(fā)生(如果能檢測(cè)属百,就可以再用戶的代碼里處理了族扰,不用留給庫(kù)去發(fā)現(xiàn)).Bjarne Stroustrup說(shuō):提供異常的基本目的就是為了處理上面的問(wèn)題定欧。基本思想是:讓一個(gè)函數(shù)在發(fā)現(xiàn)了自己無(wú)法處理的錯(cuò)誤時(shí)拋出(throw)一個(gè)異常扩氢,然后它的(直接或者間接)調(diào)用者能夠處理這個(gè)問(wèn)題.
《C++Primer》第5版中關(guān)于異常的描述是
“異常處理(exception handing) 機(jī)制允許程序中獨(dú)立開(kāi)發(fā)的部分能夠在運(yùn)行時(shí)就出現(xiàn)的問(wèn)題進(jìn)行通信并作出相應(yīng)的處理爷辱。異常使得我們能夠?qū)?wèn)題的檢測(cè)與解決過(guò)程分離開(kāi)來(lái)饭弓。程序的一部分負(fù)責(zé)檢測(cè)問(wèn)題的出現(xiàn),然后解決該問(wèn)題的任務(wù)傳遞給程序的另一部分咏花。檢測(cè)環(huán)節(jié)無(wú)須知道問(wèn)題處理模塊的所有細(xì)節(jié),反之亦然昏翰【馗福”
從以上可以看出窍株,異常機(jī)制只是一種錯(cuò)誤處理機(jī)制,它與我之前經(jīng)常用的返回true/false或錯(cuò)誤碼的方式所達(dá)到的目的一樣球订,只不過(guò)異常機(jī)制更為先進(jìn)(也是廢話,不先進(jìn)C++設(shè)計(jì)異常何用)冒滩,正如Bjarne Stroustrup書(shū)中所說(shuō)“異常處理機(jī)制是在傳統(tǒng)技術(shù)不充分开睡、不優(yōu)美和容易出錯(cuò)的時(shí)候提供的一種替代它的技術(shù)...異常處理機(jī)制提出了一種更規(guī)范的錯(cuò)誤處理風(fēng)格”篇恒,以前我總感覺(jué)用了異常就好像能夠提高程序的穩(wěn)定性胁艰,現(xiàn)在看來(lái)即使用了異常,程序該崩還是要崩奈梳。
下面是幾點(diǎn)關(guān)于異常如何使用的一些思考攘须。
1thorw異常
- 程序出現(xiàn)問(wèn)題時(shí)候throw異常
異常是只程序不應(yīng)該出現(xiàn)的情況殴泰,這與業(yè)務(wù)是密不可分的 - 異常應(yīng)該包含異常描述于宙,觸發(fā)原因和發(fā)生位置等信息
- 每個(gè)項(xiàng)目應(yīng)該有自己的異常類體系,通常應(yīng)該繼承至一個(gè)異臣璩祝基類
- 如果函數(shù)拋出異常,應(yīng)該在注釋中說(shuō)明異常類型抹恳,和拋出原因员凝,方便調(diào)用者處理
2何時(shí)catch異常
- 代碼有能力處理異常則catch。
這句話并沒(méi)有看起來(lái)那么好理解奋献,什么叫做有能力處理異常健霹,如果出現(xiàn)Mysql數(shù)據(jù)庫(kù)斷掉的異常,代碼對(duì)數(shù)據(jù)庫(kù)進(jìn)行了重新連接瓶蚂,這叫做解決了斷掉的異常糖埋,顯而易見(jiàn)這樣做可以稱之為處理了異常。但是如果不對(duì)Mysql進(jìn)行重練窃这,而是直接切換到另一個(gè)數(shù)據(jù)庫(kù)例如sqlite瞳别,而對(duì)原先的Mysql的斷掉置之不理,這應(yīng)該也算是處理異常,雖然mysql的斷掉并沒(méi)有處理跑揉。所以,有能力處理異常應(yīng)該是???可以保證程序處于業(yè)務(wù)允許的狀態(tài)下運(yùn)行望侈。 - 調(diào)用的函數(shù)中拋出與本項(xiàng)目異常體系不同的異常
例如,項(xiàng)目里面用的異常都是基于std::exception 但是調(diào)用的boost函數(shù)會(huì)拋出 boost的異常岂丘,就需要進(jìn)行捕獲。 - 需要對(duì)異常內(nèi)容進(jìn)行補(bǔ)充寨蹋,從而更方便調(diào)用者處理
- 可以斷定上層調(diào)用者無(wú)法處理該異常
這種情況多出現(xiàn)在頂層調(diào)用類中召娜,例如在典型的MVC框架中秸讹,用戶觸發(fā)View,View調(diào)用control劣欢,control調(diào)用model,此時(shí)Model會(huì)拋出異常,control發(fā)現(xiàn)無(wú)法處理該異常搔确,但通常情況下view也無(wú)法處理該異常,control應(yīng)該捕獲該異常 - 在邊界代碼中
包括系統(tǒng)涕蜂、框架調(diào)用的代碼,例如main函數(shù),框架回調(diào)函數(shù)中葱跋,系統(tǒng)和框架應(yīng)該不會(huì)捕獲你的異常。
3其它
- 所有的異常處理都應(yīng)該日志記錄
- 異常描述信息應(yīng)包含觸發(fā)的位置
- 異常處理的日志信息應(yīng)包含捕獲的位置
4思考續(xù)
通過(guò)在項(xiàng)目中對(duì)異常的實(shí)踐荠卷,發(fā)現(xiàn)其實(shí)程序中多數(shù)情況是不能解決異常的,所做的只能是進(jìn)行異常記錄验庙,開(kāi)發(fā)人員定期分析異常日志來(lái)查找程序問(wèn)題搏恤,所以我正在考慮是否只在出異常的地方進(jìn)行異常記錄藤巢,不在進(jìn)行異常拋出了。