以下面的範例,但會有以下幾個問題 :
正常
什麼時後是錯誤
。但事實上正常情況下,如果不是自幹狂或是團隊一點規範都沒有,那不然正常情況下應該不太有人會自已寫自訂錯誤碼出來。
enum ErrorCode {
SUCCESS = 0,
USER_NOT_FOUND = 1,
PERMISSION_DENIED = 2,
}
function getUser(userId: string): { data?: string; errorCode: ErrorCode } {
if (userId === "123") {
return { data: "User data", errorCode: ErrorCode.SUCCESS };
} else {
return { errorCode: ErrorCode.USER_NOT_FOUND };
}
}
就是 try catch 時 catch 裡面什麼都不寫,或是做一些處理。這個有些人看到會覺得是工程師的問題,他是痴帳或是不負責任嗎 ? 但這個事實上我覺得是幾個原因的,
其中我常看的到原因如下,它特別容易發生在一個方法用在四處的情況。
對 a 呼叫者(情境)來說,現在這個方法不是 error。
軟體工程在錯誤處理中,大部份的工程師應該都知道一個規則來決定是不是要丟例外 :
那就是從呼叫者的角度定義例外
但很慘的就是,這個可憐的方法的呼叫者就是一堆……
至於說要如何解呢 ? 我現在也想不太到比較實際的方法,然後以下只是我的想法解 :
try {
// 可能會出錯的代碼
a()
} catch (error) {
// 忽略錯誤
}
就是有些情況下,你打某個 api,然後你會看到很詳細的錯誤訊息,這個在 dev 環境還 ok,但是在 production 環境,那可能就會產生以下的問題 :
就記得在最後出去一層的地方還是要轉換一下 ~
就是 try catch 地獄,但事實上會不會發生問題,不好說,但主要影響的是以下幾個 :
function readFileContent(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
try {
const jsonData = JSON.parse(content);
console.log('JSON data:', jsonData);
return jsonData;
} catch (parseError) {
console.error('Error parsing JSON:', parseError.message);
return null;
}
} catch (readError) {
console.error('Error reading file:', readError.message);
return null;
}
}
例如下面這個 bad 的範例,他就是沒有考慮到 readSync 如果有錯誤的情況。
import * as fs from 'fs';
// Bad
function readFile(filePath: string): string {
const fileDescriptor = fs.openSync(filePath, 'r');
const buffer = Buffer.alloc(100);
fs.readSync(fileDescriptor, buffer, 0, 100, 0);
// 上面那行出錯,就不會釋放資源囉
fs.closeSync(fileDescriptor);
return buffer.toString();
}
// Good
function readFile(filePath: string): string {
const fileDescriptor = fs.openSync(filePath, 'r');
const buffer = Buffer.alloc(100);
try {
fs.readSync(fileDescriptor, buffer, 0, 100, 0);
return buffer.toString();
} finally {
// 確保文件資源被釋放
fs.closeSync(fileDescriptor);
}
}
這個東西是看 Teddy 老師寫的《笑談軟體工程:例外處理設計的逆襲》裡面所提到的強健度等級,然後整個分級如下圖 :
圖片來源: 笑談軟體工程:例外處理設計的逆襲
基本上這幾個都算很好理解,就不解釋了。然後我們家比較偏算是等級 1 與等級 2 中間。第級 2 代表的事實上就是我們常見的 transaction rollback 或是 resource cleanup 之類的,但是我們家的程式碼很多 legacy code 層層依賴且層層包,可能一個 function 產的 resource 連線四處用,有沒有 cleanup 或 rollback 都多不知道啊……因為真的很難追啊……
理想上我會想達到等級 3,但是以我們家的情況下有點難度,所以目前也只會選擇特殊的地方來做到等級 3。
在這篇文章中,我探討了軟體工程中錯誤處理設計的幾個重要看點,並對一些常見的問題進行了深入分析。以下是文章中的每一個看點:
認真的推薦 Teddy 老師寫的《笑談軟體工程:例外處理設計的逆襲》,裡面有很多東西讓我受用無窮。