8 분 소요

《클린코드》를 읽기 전까지, 나 또한 예외보다는 오류 코드로 프로그램을 다루는데에 더 익숙했다. 처음부터 그렇게 배웠다기 보다 기존의 코드들이 오류 코드를 이용하는 게 많았기 때문이다. 오류 코드보다는 예외를 사용하도록 하자! 그 어떤 프로그램도 언제든지 오류가 발생할 수 있다. 기능 구현에 급급해서 오류가 날 가능성에 대해서 미처 생각하지 못했다가는 더 큰 사고로 이어진다. try - catch - finally문 부터 작성하자.


📆TIL(Today I Learned) 날짜

2022.04.08

📑오늘 읽은 범위

7.오류 처리

✍🏻책에서 기억하고 싶은 내용

간단히 말해, 뭔가 잘못될 가능성은 늘 존재한다. 뭔가 잘못되면 바로 잡을 책임은 바로 우리 프로그래머에게 있다.

오류 처리는 중요하다. 하지만 오류 처리 코드로 인해 프로그램 논리를 이해하기 어려워진다면 깨끗한 코드라 부르기 어렵다.

👉🏻오류 코드보다 예외를 사용하라
오류가 발생하면 예외를 던지는 편이 더 낫다. 그러면 호출자 코드가 더 깔끔해진다. 논리가 오류 처리 코드와 뒤섞이지 않으니까.

👉🏻try - catch - finally문부터 작성해라.

👉🏻미확인(unchecked) 예외를 사용하라
우리는 확인된 오류가 치르는 비용에 상응하는 이익을 제공하는지 (철저히) 따져봐야 한다. (…) 확인된 예외는 OCP(Open Closed Principle)을 위반한다. 메서드에서 확인된 예외를 던졌는데 catch 블록이 세 단계 위에 있다면 그 사이 메서드 모두가 선언부에 해당 예외를 정의해야 한다. 즉, 하위 단계에서 코드를 변경하면 상위 단계 메서드 선언부를 전부 고쳐야 한다는 말이다.

👉🏻예외에 의미를 제공하라
오류 메시지에 정보를 담아 예외와 함께 던진다. 실패한 연산 이름과 실패 유형도 언급한다.

👉🏻정상 흐름을 정의하라

try {
  MeaExpenses expenses = expenseReportDAO.getMeals(employee.getID());
  m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
  m_total += getMealPerDiem();
}

특수 상황을 처리할 필요가 없다면 더 좋지 않을까? 그러면 코드가 훨씬 더 간결해지리라.

  MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
  m_total += expenses.getTotal();

청구한 식비가 없다면 일일 기본 식비를 반환하는 MealExpense 객체를 반환한다.

👉🏻null을 반환하지 마라
메서드에서 null을 반환하고픈 유혹이 든다면 그 대신 예외를 던지거나 특수 사례 객체를 반환한다.

👉🏻null을 전달하지 마라
메서드에서 null을 반환하는 방식도 나쁘지만 메서드로 null을 전달하는 방식은 더 나쁘다.

오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다. 오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지며 코드 유지보수성도 크게 높아진다.


❓궁금한 내용, 잘 이해되지 않는 내용

  • OCP(Open Closed Principle)란? 개방-폐쇄(Open Closed Principle) 원칙이란 ‘소프트 웨어 개체는 확장에 대해서는 열려(Open)있어야 하고, 수정에 대해서는 닫혀(Closed) 있어야 한다’는 프로그래밍 원칙이다. 개방-폐쇄 원칙이 잘 적용되면, 기능을 추가하거나 변경해야 할 때 이미 제대로 동작하고 있던 원래 코드를 변경하지 않아도, 기존의 코드에 새로운 코드를 추가함으로써 기능의 추가나 변경이 가능하다.
  • assert란? assert는 개발/테스트 단계에서 파라미터가 제대로 넘어왔는지 계산이 제대로 됐는지 혹은 특정 메서드가 동작하지 않는 한계 상황(Null이 들어오면 동작 안 함)을 정하는 용도로 사용한다.
assert [Boolean]  // 참이면 Pass, 거짓이면 AssertionError
void doParty(String title, int friendCount) {
    assert title == null;
    assert friendCount > 0;

    // 파티 즐기기...
}
switch (status) {
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    default:
        assert false;  // 추후 상태 값이 추가되거나 변경되면 쉽게 찾을 수 있다.
        break;
}

댓글남기기