Skip to main content

김시용

1. 📌 핵심 개념 정리

✅ 요약하기

각자 해당 챕터에서 중요하다고 느낀 개념이나 아이디어를 간략하게 정리하고 개선 전, 후에 대한 예시 코드를 비교하며 개념을 설명합니다.

  1. 오류 코드보다 예외를 사용
    오류 코드 사용할 때는 if-else로 오류 처리해서 가독성이 떨어져 호출자 코드가 복잡해진다.
    예외를 사용시, 동작과 오류 처리를 분리하여 가독성을 높인다.

  1. try-catch-finally
    예외가 발생할 코드를 짤 때는 try-catch-finally 문으로 시작하자.
    try 블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다.
    작성 tip. 강제 예외 테스트 케이스 작성 -> 테스트 통과하게 코드를 작성하기

  1. 미확인 예외 사용
    확인된 예외는 OCP (Open Closed Priciple) 위반한다. 상위 함수가 하위 함수를 호출이 반복되는 구조에서 최하위 함수에서 새로운 오류가 발견되면 그 상위 함수들 모두에 catch 혹은 throw를 수정해야 한다.
    근데 여기서 확인된 예외를 사용하면 최하위 함수의 새로운 오류를 알아야하는데 여기서 캡슐화가 깨진다.

  1. 예외 클래스 활용
    LocalPort 클래스 처럼 ACMEPort를 감싸는 클래스 유용함.
    외부 API를 감싸면 외부 라이브러리와 프로그램 사이 의존성이 크게 줄어든다. 다른 라이브러리로 교체하는데 비용이 적게들고 테스트도 쉬워짐
  • 변경전
ACMEPort port = new ACMEPort(12);

try {
  port.open();
} catch (DeviceResponseException e) {
  reportPortError(e);
} catch (ATM1212UnlockedException e) {
  reportPortError(e);
} catch (GMXError e) {
  reportPortError(e);
} finally {
  ...
}
  • 변경 후
public class LocalPort {
  private ACMEPort innerPort;

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

  public void open() {
    try {
      port.open();
    } catch (DeviceResponseException e) {
        reportPortError(e);
    } catch (ATM1212UnlockedException e) {
        reportPortError(e);
    } catch (GMXError e) {
        reportPortError(e);
    } finally {
  ...
}
  }
  1. 정상 흐름 이용
    특수 사례 패턴 활용하기 -> 특수 상황을 처리할 필요가 없다면 코드가 훨씬 간결해진다.
  • 변경 전 : 식비를 비용으로 청구했다면 직원이 청구한 식비를 총계에 더한다. 식비를 비용으로 청구하지 않았다면 일일 기본 식비를 총계에 더한다.
try {
  MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
  m_total += expenses.getTotal();
} cathch(MealExpensesNotFound e) {
  m_total += getMealPerDiem();
}
  • 변경 후 : ExpenseReportDA0를 고쳐 언제나 MealExpense 객체를 반환하게 하여 예외 처리 없애기
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();

public class PerDiemMealExpenses implements MealExpenses {
  public int getTotal() {
    // 기본값으로 일일 기본 식비를 반환
  }
}
  1. null 반환, 전달 하지마라
    null을 반환하는 코드는 예외처리 일거리만 늘어날 뿐 -> 호출자에게 문제를 떠넘김 -> null 반환 대신 빈 리스트를 반환하는 등 null 반환 안해서 예외처리 줄이기.
    null을 전달하게 되면 null을 전달 받는 곳에 예외 처리가 늘어남 -> 애초에 null 전달을 방지하기.

2. 🤔 이해가 어려운 부분

🔍 질문하기

책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.

  1. 예외 클래스 활용
    • 어려웠던 부분
      예시를 보고도 예외 클래스 활용의 장점이 와닿지 않는다.
    • 궁금한 점
      어디서 무엇이 장점인지 살펴보기
      1. 외부 라이브러리와의 의존성 줄이기
        원래 코드에서 ACMEPort를 직접 사용함 (ACMEPort 바뀌면, 코드 전반적으로 영향을 줌) -> LocalPort를 만들어 감싸면 ACMEPort가 바뀌어도 LocalPort의 내부 코드만 수정하면 됨
      2. 다른 라이브러리로 교체 쉬워짐
        ACMEPort 대신 NewPort로 바꾸려면 ACME 사용된 모든 부분 바꿔야 함
        -> LocalPort 사용하면 내부에서만 바꾸면 됨
      3. 예외 처리 통합
        기존에는 예외 처리를 ACMEPort를 사용하는 모든 곳에서 해줘야 함
        -> LocalPort가 예외를 한 곳에서 처리해주면 됨. 예를 들어, LocalPort 안에서 공통 예외 처리 후 RuntimeException으로 감싸서 던질 수도 있음.
      4. 테스트 쉬워짐 기존 코드에서는 ACMEPort를 직접 테스트해야 함
        -> LocalPort를 사용하면, ACMEPort를 가짜(Mock)로 바꿔서 테스트할 수 있음
      public class FakePort extends LocalPort {
        public void open() {
          // 테스트용 가짜 구현
        }
      }