예외 번역 (Exception Translation)
method가 저수준 예외를 처리하지 않고, 바깥으로 예외를 전파시킬 때 내부 구현 방식을 드러내어, 윗 레벨 API를 오염시킨다.
다음 릴리스에서 구현 방식을 바꾸면 기존 client 프로그램을 깨지게 만들수도 있다.
이 문제를 피하려면 상위계층에서는 저수준 예외를 잡아, 자신의 추상화 수준에 맞는 예외로 바꿔 던져야 하는데 이를 예외 번역이라고 한다.
1 2 3 4 5
| try{ }catch(LowerLevelException e){ throw new HigherLevelException(...); }
|
예외 번역의 예시로서, AbstractSequentialList 의 get method는 List 인터페이스의 get method 명세에 명시된 예외로 번역한다
1 2 3 4 5 6 7 8
| public E get(int idx){ ListIterator<E> i = listIterator(idx); try{ return i.next(); }catch(NoSuchElementException e){ throw new IndexOutOfBoundsException("인덱스: " + index); } }
|
예외 연쇄(Exception Chaining)
- 예외를 번역할 때, 저수준 예외가 디버깅에 도움된다면 근본 원인인 저수준 예외를 고수준 예외에 실어 보내는 예외 연쇄를 활용하는 게 좋다.
1 2 3 4 5
| try{ }catch(LowerLevelException cause){ throw new HigherLevelException(cause); }
|
고수준 예외의 생성자는 상위 class의 생성자에 원인을 건네주어, 최종적으로 Throwable 생성자까지 건네지게 한다.
1 2 3 4 5
| class HigherLevelException extends Exception { HigherLevelException(Throwable cause){ super(cause); } }
|
- 고수준 예외를 처리할떄, 저수준 예외 정보를 Throwable getCause method를 통해 꺼내볼수 있다.
- 대부분의 표준 예외는 예외 연쇄용 생성자를 가지고 있으며 설사 그렇지 않더라도 Throwable 의 initCause method로 원인을 직접 명시할 수 있다.
1
| public synchronized Throwable initCause(Throwable cause){}
|
권고사항
- 예외번역을 남용하는것보다 저수준 method에서 예외가 발생하지 않도록 처리해주는게 제일 좋다.
- 처리한 예외는 로깅기능을 활용해 기록해두면 API호출자가 추가 조치를 취할 수 있게 해준다.