[교재 EffectiveJava] 아이템 71. 필요 없는 검사 예외 사용은 피하라

반응형
728x90
반응형

검사 예외 사용 지양

검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다. 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다. 어떤 메서드가 검사 예외를 던질 수 있다고 선언됐다면, 이를 호출하는 코드에서는 catch 블록을 두어 처리하거나 더 바깥으로 던져 문제를 전파해야한다. (throws Exception)

 

어느 쪽이든 API 사용자에게 부담을 준다. 더구나 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없어서 자바 8부터는 부담이 더 커졌다. 

1) API를 제대로 사용해도 발생할 수 있는 예외
2) 프로그래머가 의미있는 조치를 취할 수 있는 경우

이 두가지 경우를 제외하고는 검사 예외보다는 비검사 예외를 사용하는게 좋다.

 

검사 예외가 프로그래머에게 지우는 부담은 메서드가 단 하나의 검사 예외만 던질때가 특히 크다. 이미 다른 검사 예외도 던지는 상황에서 또 다른 검사 예외를 추가하는 경우라면 catch문 하나 추가로 해결할 수 있겠지만, 검사 예외가 단 하나뿐이라면 오직 그 예외 때문에 API 사용자는 try 블록을 추가해야하고 스트림에서 직접 사용하지 못하게된다. 그러니 검사 예외를 안던지는 방법을 생각해볼 가치가 있다.

 

 

검사 예외를 회피하는 방법

1) 적절한 결과 타입을 담은 옵셔널을 반환하자. 

검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환하면 된다. 이 방식의 단점이라면 예외가 발생한 이유를 알려주는 부가정보를 담을 수 없다는 것이다. 

 

2) 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 바꾼다.

이 방식에서 첫번째 메서드는 예외가 던져질지 여부를 boolean 값으로 반환한다.

 

검사 예외를 던지는 코드
try {
    Obj.action(args);    
} catch (TheCheckedException e) {
    ... // 예외 상황에 대처한다.
}

 

리팩토링 - 상태 검사 메서드와 비검사 예외를 던지는 메서드
if (obj.actionPermitted(args)) {
    obj.action(args);
} else {
    ... // 예외 상황을 대처한다.
}

 

위 리팩토링 코드가 적절하지 않은 경우

** actionPermitted 메서드
1. 상태 검사 메서드
2. 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인에 의해 상태가 변할 수 있다면 이 리팩토링은 적절하지 않다. actionPermitted 와 action 호출 사이에 객체의 상태가 변할 수 있기 때문이다. 또한 actionPermitted가 action 메서드의 작업 일부를 중복으로 수행한다면 성능에서 손해다.

이 리팩토링을 모든 상황에 적용할 수는 없다. 그래도 적용이 가능한 부분에서는 API 사용을 더 편리하게 제공할 수 있다. 리팩토링 후의 API는 좀더 유연해졌다. 프로그래머가 이 메서드가 성공하리라는걸 안다거나, 실패시 스레드를 중단하길 원한다면 아래 한줄로 작성할 수 있다.

obj.action(args);

 

 

 

반응형

Designed by JB FACTORY