brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Aug 28. 2018

예외(Exceptions)

#57 예외 상황에서만 예외를 사용하자

Effective Java - 예외(Exception)


#57 예외 상황에서만 예외를 사용하자


// 이렇게 예외 이용 X
try {
    int i = 0;
    while(true) {
        range[i++].climb();
    }
} catch (ArrayIndexOutOfBoundsException e) {

}

while문을 이용해서 range 배열에 있는 모든 객체의 climb() 메서드를 수행하는 코드처럼? 보입니다.

만약 인덱스 값(i)이 range 배열의 크기(size) 보다 커지면, try-catch문으로 ArrayIndexOutOfBoundException 예외 발생을 검출하고, 무시하면서 이 무한 while문은 종료됩니다.


for (Mountain m : range) {
    m.climb();
}

이를 for문을 이용하면 좀 더 쉽게 구현할 수 있습니다.

둘 다 같은 동작과 결과를 얻을 수 있습니다.


그렇다면 왜 일반적인 코드로 처리 가능한 상황에서 예외를 쓰지 말아야 하는지에 대해 알아보겠습니다.




일반 코드 대비 예외 처리 코드의 단점


#01 성능 저하

기본적으로 예외는 예외 상황을 대비해 설계되었기 때문에, JVM에서 굳이 예외 처리 속도 향상이 중요하지는 않습니다.

따라서 예외 처리 코드 속도가 일반 코드보다 더 느릴 수 있습니다.


#02 가독성 저하

일반 코드를 예외 처리 코드로 만들면, 코드의 본래 목적을 혼란스럽게 하기 때문에 가독성이 떨어질 수 있습니다.


#03 부작용 발생

try-catch문을 통해 예외가 발생해도 무시될 수 있기 때문에, 개발자도 모르는 부작용이 발생할 수 도 있습니다.

이는 디버깅이 무척 어렵게 만들 수 있습니다.




기본적으로 잘 설계된 API는 클라이언트가 예외를 사용해서 정상적인 흐름을 제어하도록 하지 않습니다.


while문을 이용해서 Collection 내부에 저장된 Foo 객체들을 하나씩 꺼내는 코드입니다.

Iterator<Foo>에서 더 이상 꺼낼 객체가 없으면 NoSuchElementException 예외가 발생하고, 이를 검출-무시하고 있습니다.

try {
    Iterator<Foo> i = collection.iterator();
    while(ture) {
        Foo foo = i.next();
    }
} catch (NoSuchElementException e) {

}


Iterator 인터페이스는 상태-종속(state-dependant) 메서드와 상태-검사(state-testing) 메서드를 가지고 있습니다.

next : 상태-종속 메서드

hasNext : 상태-종속 메서드를 호출하는 것이 적합한지 나타내는 상태-검사 메서드


for(Iterator<Foo> i = collection.iterator(); i.hasNext();) {
    Foo foo = i.next
}

상태-검사 메서드를 통해 예외를 이용하지 않고 정상적인 코드 작성이 가능합니다.


이처럼 예외는 예외적인 상황에서만 이용해야 합니다.

그리고 클라이언트를 위한 API를 작성할 때는 예외를 통해 정상적인 흐름을 제어하도록 설계하면 안 됩니다.

매거진의 이전글 Effective Java - 프로그래밍 일반
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari