이펙티브 자바 10장: 예외

Adam·2024년 9월 23일
0

이펙티브 자바

목록 보기
9/10
post-thumbnail

예외는 진짜 예외 상황에만 사용하라

예외를 사용한 반복문은 성능을 떨어뜨리고 코드의 가독성을 떨어뜨린다

예외는 오직 예외 상황에만 써야하고 일상적인 제어 흐름용으로 쓰이면 안된다

잘 설계된 API라면 클라이언트가 정상적인 제어 흐름에서 예외를 사용할 일이 없게 해야 한다

옵셔널을 쓰는 지침

  1. 여러 스레드가 동시에 접근할 수 있거나 외부 요인으로 상태가 변할 수 있다면 옵셔널이나 특정 값을 사용
  2. 성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 작업 일부를 중복 수행한다면 옵셔널이나 특정 값을 선택
  3. 다른 경우엔 상태 검사 메서드가 조금 낫다

복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라

문제를 알리는 타입(throwable)dml 3 종류

  1. 검사 예외
  • 호출하는 쪽에서 복구하리라 여겨지는 상황에서 사용
  • 복구에 필요한 정보를 알려주는 메서드를 함께 제공하는 것이 좋다
  1. 런타임 예외
  • 프로그래밍 오류를 나타낼 때 사용
  • 대부분은 클라이언트가 API 명세에 기록 된 제약을 지키지 못했을 때 발생
  1. 에러
  • JVM이 자원 부족, 불변식 깨짐 등 더 이상 수행을 계속할 수 없는 상황을 나타냄
  • Error 클래스를 상속해 하위 클래스를 만들지 말아야 하고, 구현하는 비검사 throwable은 모두 RuntimeException의 하위 클래스여야 한다

필요 없는 검사 예외 사용은 피하라

검사 예외를 제대로 활용하면 API와 프로그램의 질을 높일 수 있다

검사 예외는 문제를 프로그래머가 처리하여 안전성을 높일 수 있다

검사 예외를 회피하는 가장 쉬운 방법은 적절한 결과 타입을 담은 옵셔널을 반환하는 것

옵셔널만으로는 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지는게 좋다

표준 예외를 사용하라

예외를 재사용하는 것이 좋으며, 자바 라이브러리는 대부분 API에서 쓰기에 충분한 수의 예외를 제공

표준 예외의 장점

  1. API가 다른 사람이 익히고 사용ㅇ하기 쉬워진다
  2. 예외 클래스가 적을 수 록 메모리 사용량도 줄고 클래스를 적재하는 시간도 적게 걸린다

IllegalArgumentException: 호출자가 부적절한 값을 넘길 때 던지는 예외

IllegalStateException: 대상 객체의 상태가 호출된 메서드를 수행하기에 적합하지 않을 때 사용

ConcurrentModificationException: 단일 스레드에서 사용하려고 설계한 객체를 여러 스레드가 동시에 수정하려 할 때 사용

UnsupportedOperationException: 클라이언트가 요청한 동작을 대상 객체가 지원하지 않을 때 사용

추상화 수준에 맞는 예외를 던지라

예외 번역: 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야 한다.

예외 번역을 남용해서는 안된다

예외 연쇄를 이용하면 상위 계층에는 맥락에 어울리는 고수준 예외를 던지면서 근본 원인도 함께 알려주어 오류를 분석하기 좋다

메서드가 던지는 모든 예외를 문서화하라

메서드가 던지는 예외는 그 메서드를 올바로 사용하는 데 아주 중요한 정보

검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화해야 한다

비검사 예외도 검사 예외처럼 정성껏 문서화해두면 좋지만 메서드 선언의 throws 목록에 넣지는 않아야 한다

예외의 상세 메시지에 실패 관련 정보를 담으라

실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 한다

실패를 적절히 포착하려면 필요한 정보를 예외 생성자에서 모두 받아서 상세 메시지까지 미리 생성해놓는 방법도 괜찮다

가능한 한 실패 원자적으로 만들라

실패 원자적: 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출ㄹ 전 상태를 유지해야 한다

실패 원자적으로 만드는 방법

  1. 작업 수행에 앞서 매개변수의 유효성을 검사하는 것
  2. 실패할 가능성이 있는 모든 코드를, 객체의 상태를 바꾸는 코드보다 앞에 배치하는 것도 하나의 방법
  3. 작업 도중 발생하는 실패를 가로채는 복구 코드를 작성하여 작업 전 상태로 되돌리는 방법

실패 원자성을 사용하지 않아야 하는 경우

  1. 멀티스레드 환경에서는 객체의 일관성이 깨질 수 있다
  2. 실패 원자성을 달성하기 위한 비용이나 복잡도가 큰 경우

예외를 무시하지 말라

catch 블록을 비워두면 예외가 존재할 이유가 없어진다

예외를 무시하기로 했다면 catch 블록 안에 그렇게 결정한 이유를 주석으로 남기고 예외 변수의 이름도 ignored로 바꾸어 놓자

profile
Keep going하는 개발자

0개의 댓글