Skip to content

아이템 69. 예외는 진짜 예외 상황에만 사용하라 - Fin #163

Description

@Irisation23

Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/157

Originally posted by bunsung92 March 14, 2023
📝 구성


0. TL;DR 🔨

예외를 정상 흐름에서 제어를 위해 사용하면 안된다.
또, 정상 흐름에서 제어하기 위해 예외를 사용해야하는 API 를 만들면 안된다.

그러기 위해서는 상태 의존적 메서드, 옵셔널, 특정값 반환등의 방법을 제공할 수 있다.


1. 들어가기에 앞서 🤔

예외의 활용은 프로그램의 가독성, 신뢰성, 유지보수성을 높일 수 있다.
하지만 사용방법이 올바르지 못하다면 이와 반대의 효과를 가지게 된다.
어떻게 하면 효과적인 예외를 처리 할 수 있을지 고민해 보며, 예외 파트로 들어가 보자.


2. 잘못된 예외 사용

try {
    int i = 0;
    while(true) {
        range[i++].climb();
    } 
} catch (ArrayIndexOutOfBoundsException e) {
    
}

해당 코드 내용을 보면 대체 뭘하는 코드인지 알 수가 없다.
실제로 해당 코드는 배열의 끝에 도달해 ArrayIndexOutOfBoundsException가 발생하면 끝을 내는 코드이다.

해당 코드는 표준 관용구였다면 그냥 넘어 갈 수있다.

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

첫번째와 같은 예외 코드를 작성한 이유는 성능을 높이기 위해서이다.
JVM은 배열에 접근할 때 인덱스를 초과하는지 확인하는데, 반복문도 이와 같은 동작을 수행한다.
따라서 중복을 없애기 위해 예외를 사용한 것이다.

하지만 이는 다음의 세가지 이유로 잘못된 추론이다.

  1. 예외는 예외 상황에서 쓰이기 위해 만들어 졌기 때문에, JVM설계자가 성능적 측면을 고려하지 않았다.
  2. try-catch 블럭 안에서는 JVM이 수행하는 최적화가 제한된다.
  3. 앞서 본 예제에서의 중복 검사는 실제로 중복으로 수행되지 않는다. JVM이 최적화를 통해 없애기 때문이다.

뿐만아니라 이 메서드의 이용은 Side Effect 에 노출 되어있을 가능성있다.
만약 첫번째 예시에서 의도치 않은 곳에서 ArrayIndexOutOfBoundsException이 발생할 경우
프로그램은 종료되지 않고 계속 수행될 것이고, 이는 다른 곳에 영향을 주어 잘못 동작할 수 있다.

2.1 예외를 제어 흐름에 사용하면 안된다.

  1. 코드가 무엇을 하는지 알기 힘들다.
  2. 성능에도 큰 도움이 되지 않는다.
  3. 의도치 않은 오작동을 야기한다.

3. API 설계시의 예외

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

특히 특정 상태에서 호출할 수 있는 메서드는 상태 검사 메서드를 함께 제공해야 한다.

Iterator
특정 상태에서만 호출할 수 있는 메서드 : next()
상태 검사 메서드 : hasNext()

Iterator API는 이처럼 hasNext를 함께 제공함으로써, 클라이언트가 직접 예외를 사용하지 않아도 되도록 설계하였다.
만약 상태 검사 메서드를 직접 제공하지 않는 경우에는 Optional 혹은 null과 같은 특수한 값을 반환하도록 해야 한다.

3.1 상태 검사 메서드, 옵셔널, 특정 값(null) 선택의 지침

  1. 여러 스레드가 동시에 접근가능하거나 외부에서 상태를 바꿀 수 있다

옵셔널이나 특정 값을 사용한다.
상태 검사 메서드와 상태 의존적 메서드의 동작 사이에 값이 변해버릴 수 있다.

  1. 성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 일과 중복되는 일을 한다.

옵셔널이나 특정 값을 사용한다.

  1. 다른 모든 경우에는 상태 검사 메서드, 상태 의존적 메서드를 제공하자.

4. 핵심 정리 📚

예외는 예외 상황에서 쓸 의도로 설계되었다.
정상적인 제어 흐름에서 사용해서는 안되며, 프로그래머에게 강제하는 API를 둬서도 안된다.

5. 회고 🧹

2023-03-19 일

  • Optional이 수 많은 기능을 담고 있다는 점을 항상 인지하면서 따로 Optional 파트의 정리를 이어나가야 함을 기억하자.
  • 필요에 따라서는 null을 직접적으로 던지기도 한다는 것도 인지하자.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

10장 예외이펙티브 자바 10장 (예외)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions