iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 5
0
Software Development

後端攻城獅的實戰筆記系列 第 5

例外處理!?能吃嗎 下

前言

上集講了一些很迷迷糊糊的原則,大家484很想把我毆飛阿。

下集讓我彌補一下,今天就來講一些實例的部份。

實例

  • Don't Ignore Exception
catch (Exception ex) {
  // didn't do anything even logging
}

catch (Exception ex) {
  // print stack trace is useless
  ex.printStackTrace();
}
  • Just Let Unchecked Exception Spread
如果你的例外處理姿勢正確,應當讓非受檢例外自己傳播
  • 使用 UnhandledException (extends RuntimeException) 傳遞 Checked Exception。但理論上這個例外在重構之後就會被更名成更有意義的名字。
catch (IOException ex) {
  throw new UnhandledException(ex);
}
  • Don't Throw Exception Again after Log It
這是沒有意義的也會導致重複記錄,影響效能又增加除錯困難。

catch(FileNotFoundException ex) {
    logger.error(ex.getMessage(), ex);
    throw new UnhandledExcpeiton
}
  • 建立一個最外層的 Try Catch Block 避免 Context 崩毀,可以像是下面的程式,或是像 Spring 有 ControllerAdvice。
public static void main(String[] args) {
  try {
    // a lot of business logic
  } catch (Exception ex) {
    // catch it at process it (maybe logger it)
  }
}
  • Don't name too general, you must name by exception cause
X ATMExcpetion
X WithdrawException
O NotEnoughMoneyException
  • 轉換成高階模組看的懂的例外
因為寫進 File,你可能原本是這樣實作
public void saveConfig() throw IOException

後來改成寫進資料庫,你變成這樣實作
public void saveConfig() throw SQLException

可是一旦你修改了,外部相依的的程式就必須跟著修改,所以最好一開始就這樣宣告。
public void saveConfig() throw ConfigModifyException
  • Homogeneous Exception
如果你實作一個資金相關的類別,可能會有以下方法。
balance() throws IOException, SQLException
withdraw() throws IOException, SQLException
deposit() throws IOException, SQLException

為了符合轉換成高階模組看的懂的例外,有些人會這樣改。
balance() throws BalanceException
withdraw() throws WithdrawException
deposit() throws DepositException

但這樣又會產生過多的例外類別,所以建議同質性的例外可以寫成一樣。
balance() throws FundException
withdraw() throws FundException
deposit() throws FundException
  • Exception Wrapping
承上,現在大家都叫做 FundException 了,萬一都抓到這個一定又分布出來。
實務上要分辨它們招式也是挺多。

你可以用繼承的讓它們具有階層關係,也可以在定義不同的 field 或是 Enum 塞在 Exception 裡頭。
  • Don't user nested Try Catch block
這樣寫應該不需要我來解釋這有多糟糕。
最簡單的作法請至少把 Try Block 重構成 Method。

try {
  // some logic ...
} catch (Exception ex) {
  try {
    // some logic again ...
  } catch (Exception ex) {
    // ...
  }
}
  • Spare Handler
簡單來說,不要用 Try Catch Block 來控業務邏輯。

try {
  // main solution
} catch (Exception ex) {
  // alternative solution
}
  • Careless Cleanup
try {
  FileInputStream fis = new FileInputStream(new File("abc.txt"));
  fis.close(); // oh my god, please close it on finally block!
} catch (IOException ex) {
  // ...
}
  • Don't use Return Code
這個在某語言其實很常見,時代的眼淚。
其實 Java 已經高度物件導向,用 Exception 來表達會更好。

/*
  return 1 = success
  return -1 = not enough balance
  return -2 = ...
*/
public int withdraw(int amount) {
  // some logic ...
}

About Me

Jian-Min Huang

wide range skill set backend engineer

Research, Architecture, Coding, DB, Ops, Infra.

mainly write Java but also ❤️ Scala, Kotlin and Go

http://github.jianminhuang.cc

http://linkedin.jianminhuang.cc

http://note.jianminhuang.cc

yfr.huang@hotmail.com


上一篇
例外處理!?能吃嗎 上
下一篇
程式也會貧血或充血?
系列文
後端攻城獅的實戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言