-
[Effective Java] 필요 없는 검사 예외 사용은 피하라Java 2023. 2. 6. 12:47
필요 없는 검사 예외 사용은 피하라
검사 예외를 싫어하는 자바 프로그래머가 많지만 제대로 활용하면 API와 프로그램의 질을 높일 수 있다.
결과를 코드로 반환하거나 비검사 예외를 던지는 것과 달리, 검사 예외는 발생한 문제를 프로그래머가 처리하여 안정성을 높이게끔 해준다.
- 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다.
- 어떤 메서드가 검사 예외를 던질 수 있다고 선언됐다면, 이를 호출하는 코드에서는 catch 블록을 두어 그 예외를 붙잡아 처리하거나 더 바깥으로 던져 문제를 전파해야 한다.
검사 예외 회피 방법 - 1. 비검사 예외
API를 제대로 사용해도 발생할 수 있는 예외이거나, 프로그래머가 의미 있는 조치를 취할 수 있는 경우라면 이 정도 부담쯤은 받아들일 수 있을 것이다.
하지만 이 경우들이 아니라면, 비검사 예외를 사용하는 것이 좋다.
아래 두 코드는 프로그래머(API 사용자)가 검사 예외를 책임지는 사례다.
}catch(TheCheckedException e){ throw new AssertionError(); }
}catch(TheCheckedException e){ e.printStachTrace(); System.exit(1); }
첫 번째 코드는 프로그래머가 비검사 예외를 호출하는 것으로 해결했했다.
두 번째 코드는 에러 스택 코드를 호출하고 시스템을 종료시킨다.두 경우 모두 애초에 비검사 예외로 API를 만들면 됐을 것이다.
검사 예외 회피 방법 - 2. Optional
검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하는 것이다.
- 검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환하면 된다.
- 이 방식의 단점은 예외가 발생한 이유를 알려주는 부가 정보를 담을 수 없다는 것이다. (예외를 사용하면 구체적인 예외 타입과 그 타입이 제공하는 메서드들을 활용해 부가 정보를 제공할 수 있다.)
검사 예외 회피 방법 - 3. 메서드 쪼개기
또 다른 방법으로, 검사 예외를 던지는 메서드를 2개로 쪼개 비검사 예외로 바꿀 수 있다.
//메서드 쪼개기 전 (리팩터링 전) try{ obj.action(args); }catch(TheCheckedException e){ // ... }
//메서드 쪼갠 후 (리팩터링 후)) try(obj.actionPermitted(args)){ obj.action(args); }else{ // ... }
action 내의 로직을 2개의 메소드 (actionPermitted, action)으로 나눴다.
리팩터링 후의 API가 더 아름답진 않지만, 더 유연하다.한편, actionPermitted는 '상태 검사 메서드'에 해당하므로 주의해야 한다.
- 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인에 의해 상태가 변할 수 있다면 이 리펙토링은 적절하지 않다.
- actionPermitted와 action 호출 사이에 객체의 상태가 변할 수 있고, 또 두 메서드가 동일한 로직을 중복해서 가지고 있을 수 있기 때문이다.
핵심 정리
- 꼭 필요한 곳에만 사용한다면 검사 예외는 프로그램의 안전성을 높여주지만, 남용하면 쓰기 고통스러운 API를 낳는다.
- API 호출자가 예외 상황에서 복구할 방법이 없다면 비검사 예외를 던지자.
- 복구가 가능하고 호출자가 그 처리를 해주길 바란다면, 우션 옵셔널을 반한해도 될지 고민하자.
- 옵셔널 만으로는 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지자.
'Java' 카테고리의 다른 글
[Effective Java] wait와 notify보다는 동시성 유틸리티를 애용하라 (0) 2023.02.14 [Effective Java] 스레드보다는 실행자, 태스크, 스트림을 애용하라 (0) 2023.02.14 [Effective Java] 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라 (0) 2023.02.06 [Effective Java] 예외는 진짜 예외 상황에만 사용하라 (0) 2023.02.06 [Effective Java] 다른 타입이 적절하다면 문자열 사용을 피하라 (1) 2023.02.03