Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Irisation23 opened this issue Mar 19, 2023 Discussed in #157 · 0 comments
Open

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

Irisation23 opened this issue Mar 19, 2023 Discussed in #157 · 0 comments
Assignees
Labels
10장 예외 이펙티브 자바 10장 (예외)

Comments

@Irisation23
Copy link
Member

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을 직접적으로 던지기도 한다는 것도 인지하자.
@Irisation23 Irisation23 added the 10장 예외 이펙티브 자바 10장 (예외) label Mar 19, 2023
@Irisation23 Irisation23 self-assigned this Mar 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
10장 예외 이펙티브 자바 10장 (예외)
Projects
None yet
Development

No branches or pull requests

1 participant