---
# System prepended metadata

title: Clean Code - Ch07 錯誤處理
tags: [Clean Code, Book]

---

# Clean Code - Ch07 錯誤處理
錯誤處理很重要，但如太雜亂而導致我們模糊了原本代碼的邏輯，那就是不對的

## 1. 使用 try catch 而非回傳錯誤碼
這樣會讓代碼變得雜亂而且必須在結果回傳後馬上使用，不然的話你不能保證它在後續的代碼中直到你驗證之前是不是有被偷偷修改過，而且很容易在寫代碼的過程中忘記還有這段東西
而且可以讓代碼變得簡潔，可以專注在你的邏輯上面
**Bad：**
``` csharp
public void SendData() 
{
    var result = this.Send(data);    
    if(result.Status != status.InValid)
    {
        log.Error(ex, "Send Error!");
    } 
}
```
**Good：**
``` csharp
public void SendData() 
{
    try
    {
        var result = this.Send(data);   
    }
    catch (Exception ex)
    {
        log.Error(ex, "Send Error!");
    }
}
```

## 2. 在開頭寫下 try catch finally
這樣可以幫助你定義好的你的function的職責區塊，你可以很明確的知道代碼的流程以及報錯時的處理

***但我覺得這一段有點過頭，因為try catch finally 它的區塊是各自分開的，所以它會變成要把一些變數定義成全域變數，反而變成會寫出一些受到汙染的代碼***

[出處](http://teddy-chen-tw.blogspot.com/2013/04/clean-code.html)

## 3. catch裡要盡量提供足夠的相關資訊
比方說 **stack的堆疊資訊(function的調用順序、報錯在哪行等等)**，讓查bug的人可以正確的推斷到底是做什麼行為後才導致出錯
***現在的log套件應該都有支援這部分的功能了，所以不用太擔心***

## 4. 定義共用的exception，並把catch exception根據不同的library設計不同的界接class
這樣可以讓exception統一而且之後換掉第三方library後，稍微改動一下就可以無縫接軌
***有好處也有壞處，但感覺有機會變過度設計***
**Bad：**
``` csharp
public void DoSomething () 
{
  ACMEPort port = new ACMEPort (12);

  try {
    port.close ();
  } catch (DeviceResponseException e) {
    reportPortError (e);
    logger.log ("Device response exception", e);
  } catch (ATM1212UnlockedException e) {
    reportPortError (e);
    logger.log ("Unlock exception", e);
  } catch (GMXError e) {
    reportPortError (e);
    //logger.log("Device response exception", e);
    logger.log ("Device response exception");
  } finally {
    //...
  }
}
```
**Good：**
``` csharp
public void DoSomething () 
{
  LocalPort port = new LocalPort (12);
  try {
    port.open ();
  } catch (PortDeviceFailure e) {
    reportError (e);
    logger.log (e.getMessage (), e);
  } finally {
    //...
  }
}

public class LocalPort
{
  private ACMEPort innerPort;

  public LocalPort (int portNumber) {
    innerPort = new ACMEPort (portNumber);
  }

  public void open () {
    try {
      innerPort.open ();
    } catch (DeviceResponseException e) {
      throw new PortDeviceFailure (e);
    } catch (ATM1212UnlockedException e) {
      throw new PortDeviceFailure (e);
    } catch (GMXError e) {
      throw new PortDeviceFailure (e);
    }
  }
}
```

## 5. 不要在exception裡面處理商業邏輯
這樣會導致流程跟邏輯混在一起，而且後面的部分就不用再針對exception處理裡面的例外邏輯
**Bad：**
``` csharp
public int GetBilling()
{
    var billing = new BillingDA();
    
    try
    {
        total += billing.GetTotalBilling();
    }
    catch (Exception ex)
    {
        total = billing.RefreshTotal();
    }
}
```

## 6. 不要回傳null，應該response empty list等數據
因為容易變成只要後續一個地方沒加上null判斷就會容易出現null exception
***這部分是書上建議，要不要response null，看每個專案的需求及團隊的寫作習慣***

## 7. 不要傳null給function或任何東西
因為這樣會變成你還要在function裡面加上判空，除非那個null是邏輯的一部分
***這部分是書上建議，要不要response null，看每個專案的需求及團隊的寫作習慣***

## 總結
第6、7點其實應該是寫代碼本來就應該避免的問題，但因為這章是在講exception
而作者又預設只要null或出錯就該報exception，因此才會放在這裡

###### tags: `Clean Code` `Book`