[Item 73] 추상화 수준에 맞는 예외를 던지라

2022. 8. 28. 12:14JAVA/Effective Java

메서드가 저수준 예외를 처리하지 않고 바깥으로 전파했을 때

  • 수행하려는 일과 관련 없어 보이는 예외가 발생
  • 내부 구현 방식을 드러내어 윗 레벨API를 오염
  • 구현 방식을 바꾸면 다른 예외가 발생하여 기존 클라이언트 프로그램을 깨지게함.

예외 번역(exception translation)

- 위 문제를 피하기 위해선 상위 계층에서 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로

바꿔 던져야한다.(예외 번역)

try{
 //저수준 추상화를 이용
}catch(LowerLevelException e){
 //추상화 수준에 맞게 번역
 throw new HigherLevelException("exception");
}
//AbstractSequentialList에서 수행하는 예외번역 예시

public abstract class AbstractSequentialList<E> extends AbstractList<E> {
    /**
     * Sole constructor.  (For invocation by subclass constructors, typically
     * implicit.)
     */
    protected AbstractSequentialList() {
    }

    /**
     * Returns the element at the specified position in this list.
     *
     * <p>This implementation first gets a list iterator pointing to the
     * indexed element (with <tt>listIterator(index)</tt>).  Then, it gets
     * the element using <tt>ListIterator.next</tt> and returns it.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }
}

예외를 번역할 때, 저수준 예외가 디버깅에 도움이 된다면 예외 연쇄 (exception chaining)를 사용하는 게 좋다.

 

예외 연쇄(exception chaining)

- 예외 연쇄는 문제의 근본 원인인 저수준 예외를 고수준 예외에 실어내는 방식

try{
 //저수준 추상화를 이용
}catch(LowerLevelException e){
 //저수준 예외를 고수준 예외에 실어보낸다.
 throw new HigherLevelException(e);
}

상위 클래스의 생성자에 이 원인을 건내주어 최종적으로 Throwable 생성자까지 건내게 된다.

그러면 별도의 접근자 메서드(Throwable의 getCause 메서드)로 언제든 저수준 예외를 꺼내볼 수 있다.

class HigherLevelException extends Exception {
    HigherLevelException(Throwable cause) {
        super(cause);
    }
}
  • Throwable의 initCause 메서드로 원인을 직접 못받을 수도 있다.
  • 예외 연쇄는 문제의 원인에 접근하여 원인과 고수준 예외의 스택 추적 정보를 잘 통합해준다.
  • 예외를 무턱대고 전파하는 것보다 예외 번역이 우수하지만, 남용하면 안된다. -> 가능하면 저수준 메서드가 성공하도록 하여 예외를 발생시키지 않는 것이 최선이다.
  • 아래 계층에서 예외를 피할 수 없다면, 상위 계층에서 조용히 처리하여 API 호출자까지 전파하지 않는 방법이 있다. 이럴 때는 발생한 예외를 적절한 로깅 기능으로 기록해 두어야 한다.

핵심정리

  • 아래 계층의 예외를 예방하거나 스스로 처리할 수 없고, 그 예외를 상위계층에 그대로 노출하기 곤란하다면 예외 번역을 사용하라.
  • 이 때 예외 연쇄를 사용하면 상위 계층에는 맥락에 어울리는 고수준 예외를 던지면서 근본 원인도 함께 알려주어 오류 분석에 좋다.

참고자료

www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788966262281&orderClick=LEa&Kc=

 

이펙티브 자바 3/E - 교보문고

프로그래밍인사이트 | 자바 6 출시 직후 출간된 『이펙티브 자바 2판』 이후로 자바는 커다란 변화를 겪었다. 그래서 졸트상에 빛나는 이 책도 자바 언어와 라이브러리의 최신 기능을 십분 활용

www.kyobobook.co.kr