규칙 61 - 추상화 수준에 맞는 예외를 던져라

JAVA/Effective Java|2018. 6. 1. 23:05

메서드가 하는 일과 관련성이 없는 예외가 메서드에서 발생하면 디버깅하기 어렵거나 관리하기 어려울 수 있다.


이는 추상화 수준이 낮은 곳에서 발생한 예외를 그대로 밖으로 전달하면 이런일이 발생한다.



이런 문제를 해결하기 위해서 상위계층에서는 하위계층에서 발생하는 예외를 반드시 받아서 상위 계층 추상화 수준에 맞는 예외로 바꿔서 던져야한다.


이를 예외 변환(exception translation)이라고 한다.



예를 들어 몇가지 사례를 살펴보자.


우선 AbstractSequentialList 클래스를 살펴보자. 이 클래스의 get 메서드의 명세를 보면 예외가 발생되었을 때 예외 변환을 해서 보내달라는 것을 확인할 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 /**
     * 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);
        }
    }
cs





그리고 예외 변환의 특별한 사례인 예외 연결 (exception chaining)이있다. 


이는 하위 계층에서 발생한 예외정보가 상위계층 예외를 발생시킨 문제를 디버깅 할때 사용한다.


사용방법은 원인이 상위 계층 예외로 전달되는데, 상위 계층 예외에 있는 Throwable.getCause를 호출하면 해당 정보를 꺼낼 수 있다.




[예외 연결]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 
/**
 * 상위계층 에러인 wedulError
 * 
 * @author jeongcheol
 *
 */
public class WedulError extends Exception {
    public WedulError(Throwable cause) {
        super(cause);
    }
}
 
 
 
 
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
 
public class Main {
 
    public static void main(String args[]) throws WedulError {
        
        List<String> data = Arrays.asList("cjung""wedul");
        try {
            data.get(3);
        } catch (NoSuchElementException e) {
            throw new WedulError(e);
        }
    }
    
}
 
 
cs



이런 예외 연결 기능을 사용하면 프로그램 안에서 예외의 원인에 접근할 수 있을뿐 아니라 최초에 발생한 예외의 스택 추적 정보를 상위계층 예외에 통합할 수 있다.




결론은 아무 생각없이 아래 계층에서 생긴 예외를 밖으로 전달하기만 하는 것보다야 예외 기법 낫지만 남용해서는 안된다.

제일 좋은 방법은 아예 에러없는 코딩을 하는 것이다.


그리고 하위계층에서 발생한 에러는 하위계층에서 처리하고 어쩔수 없이 전달될경우에는 적절한 예외로 예외 변환해서 보내야한다.




출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙61 인용.

댓글()