我們在設計函數時,通常要考量函數之中發生錯誤時應如何處理?這一方面的知識沒有捷徑,通常需要仰賴足夠的設計經驗以為準則。概略而言可分兩部份來談:其一是錯誤回報;其二是資源回收。
由於此文是我回應 Tokimeki 的 PHP 文章之內容整理而來,故會夾雜一些 PHP 的例子。
我們在設計函數時,通常要考量函數之中發生錯誤時應如何處理?這一方面的知識沒有捷徑,通常需要仰賴足夠的設計經驗以為準則。概略而言可分兩部份來談:其一是錯誤回報;其二是資源回收。
由於此文是我回應 Tokimeki 的 PHP 文章之內容整理而來,故會夾雜一些 PHP 的例子。
錯誤回報亦即回傳 (return) 或擲出 (throw) 錯誤狀況給調用者。回傳或擲出錯誤狀況之策略選擇,依設計經驗而有明確的使用情境。
return 0; 表示成功,其他值為失敗代號。return FALSE; 表示錯誤, 其他值表示成功。throw 是唯一能夠告知調用者錯誤原因的途徑。
return FALSE; 表示失敗,失敗原因儲放在另一個資料成員中。但此法通常不保證 Multi-thread 作業安全。
函數回傳方式於 PHP manual 中的慣用說明形式。通常看到某函數的說明形式時,就可以判斷該函數的錯誤處理策略。
void myfunc();try {
myfunc();
}
catch (MyException $e) {
echo $e;
}bool myfunc(); int myfunc();mixed myfunc();if (($result = myfunc()) === FALSE) {
echo 'Error';
}
mixed myfunc(); throw exceptiontry {
$results = myfunc();
}
catch (MyException $e) {
echo $e;
}
函數式語言中規定函數不可以有副作用。在程序式語言中同樣可以如此檢視一個函數是否設計得宜。所謂沒有副作用,簡單地說是指在調用函數之前後,除了函數回傳值外,沒有其他狀態改變。通常我們會檢查函數在回傳前,是否釋放了其配置之資源。
同理,當函數之中發生錯誤時,函數也應該先釋放它先前要求配置的資源之後,才進行錯誤回報動作。如果發生錯誤後便直接回傳或擲出錯誤,而沒有先釋放函數中配置的資源,那麼程式中便會同時存在兩個以上的狀態變動,一是錯誤狀態,其他就是資源配置狀態 之變動。除增加整個錯誤處理程序的複雜度,也將為程式主體帶來副作用。
本文以我個人的設計經驗為主,而我是從 BASIC (我指的是 QuickBASIC 而非 VisualBASIC), Assembly, C/C++ 一路走過來的,大部份設計經驗是在這一段時間中定型。基本上不只適用 PHP ,也適用於其他程式語言。