Clean Code: 오류 처리

jiffydev·2021년 5월 31일
0

Clean Code

목록 보기
6/13

깔끔한 오류 처리가 깨끗한 코드를 만든다.

1. Try-Catch-Finally 문부터 작성

  • 예외가 발생할 코드라면 try-catch-finally 문으로 시작하는 편이 낫다.

  • try-catch 구조로 범위를 정의하고, TDD를 통해 나머지 논리를 추가한다.

  • 먼저 강제로 예외를 일으키는 테스트 케이스를 작성 후 테스트를 통과하게 코드를 작성하면 자연스럽게 try 블록의 트랜잭션 범위부터 구현하게 되므로 트랜잭션 본질을 유지하기 쉬워진다.

2. unchecked 예외를 사용

  • checked 예외를 사용할 때 드는 비용보다 이익이 더 클 때만 사용한다.

  • checked 예외는 하위 단계 메서드에 예외를 추가하면 모든 상위 단계 메서드에도 해당 예외를 정의해야 한다.

  • 이는 OCP(개방-폐쇄 원칙)를 위반하고 캡슐화를 깨뜨린다.

3. 호출자를 고려해 예외 클래스를 정의

  • 오류를 정의할 때 가장 중요한 관심사는 오류를 잡아내는 방법이어야 한다.

  • 예외에 대응하는 방식이 예외 유형과 무관하게 동일하다면 wrapper 클래스를 통해 예외 유형 하나만을 반환하도록 할 수 있다.

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;
  
  pblice 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);
    }
  }
  ...
}
  • 외부 라이브러리인 ACMEPort 클래스를 LocalPort 클래스로 감싸게 되면 의존성이 줄어들어 다른 라이브러리로 갈아타도 비용이 적다. 또한 특정 프로그램의 설계방식에 발목 잡히지 않는다.

4. 정상 흐름을 정의

  • 특수 사례 패턴을 통해 클래스/객체가 예외적인 상황을 캡슐화하여 처리하도록 함으로써 예외처리를 하지 않을 수도 있다.
// Before
try {
  MealExpenses expenses = ExpenseReportDAO.getMeals(employee.getID());
  m_total += expenses.getTotal();
} catch (MealExpenseNotFound e) {
  m_total += getMealPerDiem();
}

// After
MealExpenses expenses = ExpenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();

public class PerDiemExpenses implements MealExpenses {
  public int getTotal() {
    // 기본값으로 일일 식비를 반환
  }
}
  • ExpenseReportDAO를 고쳐 언제나 MealExpense 객체를 반환하고, 청구한 식비가 없다면 일일 기본 식비를 반환하는 MealExpense 객체를 반환한다.

5. null을 반환하지 마라

  • null을 반환하는 코드는 호출자에게 문제를 떠넘긴다.

  • null 확인이 너무 많다면 예외를 던지는 것으로 바꾸거나 특수 사례 객체를 반환하도록 한다.

  • 외부 API가 null을 반환한다면 wrapper 메소드를 구현해 예외를 던지거나 특수 사례 객체를 반환한다.

6. null을 전달하지 마라

  • 정상적인 인수로 null을 기대하는 API가 아닌 이상 메서드 인수로 null을 전달하는 것은 피한다.

  • 대다수 프로그래밍 언어는 호출자가 실수로 넘기는 null을 적절히 처리하는 방법이 없으므로, 정책으로 null을 넘기지 못하도록 하는 것이 합리적이다.

profile
잘 & 열심히 살고싶은 개발자

0개의 댓글