Skip to content

Commit

Permalink
[Item69]: 예외는 진짜 예외 상황에서만 사용하라 (#158)(도모) (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdomo authored Sep 10, 2023
1 parent b83d9d5 commit 0bdad39
Showing 1 changed file with 63 additions and 0 deletions.
63 changes: 63 additions & 0 deletions Ch10/item69/예외는_진짜_예외_상황에만_사용하라.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# item69. 예외는 진짜 예외 상황에만사용하라

### 예외는 정말 예외적인 상황에서만 사용해야 한다.
- 예외는 오직 예외 상황에서만 사용해야 한다. 절대로 일상적인 제어 흐름용으로 쓰여선 안된다.
- 이를 프로그래머에게 API를 만들어서도 안된다.

### 예외를 사용하는 부적절한 예
```java
// 코드 69-1 예외를 완전히 잘못 사용한 예 - 따라 하지 말 것! (419쪽)
try {
int i = 0;
while(true)
range[i++].climb();
} catch (ArrayIndexOutOfBoundsException e) {
}
```
- 이 코드는 반복문을 종료하는 용도로 예외를 사용한다.
- 직관적이지 않다는 점 외에 성능 문제도 있다.

### 표준적인 관용구를 사용한 반복문
```java
// 코드 69-2 표준적인 관용구를 사용한 반복문 (419쪽)
for (Mountain m : range)
m.climb();
```
- 위 코드는 표준적인 관용구를 사용한 반복문이다.
- 이 코드는 예외를 사용하지 않으므로 성능도 훨씬 좋다.

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

1. 상태 검사 메서드
특정 상태에서만 호출할 수 있는 ***상태 의존적 메서드***를 제공하는 클래스는, ***상태 검사 메서드도 함께 제공***한다면 예외를 사용하지 않을 수 있다.</br>
`Iterator` 인터페이스를 예시로 들어보자. `next` 는 상태 의존적 메서드, `hasNext` 는 상태 검사 메서드에 해당한다.
```java
// 두 메서드 덕분에 표준 for 관용구를 사용할 수 있음
for (Iterator<Foo> i = collections.iterator(); i.hasNext(); ) {
Foo foo = i.next();
}
```

만약 `Iterator``hasNext`를 제공하지 않았다면 그 일을 다음과 같이 클라이언트가 대신 했어야 할 것이다.</br>
```java
try {
Iterator<Foo> i = collection.iterator();
while(true) {
Foo foo = i.next();
...
} catch (NoSuchElementException e) {
}
```
이처럼 반복문에 예외를 사용하면 코드가 헷갈리고 성능도 좋지 않으며, 엉뚱한 곳에서 발생한 버그를 본의 아니게 숨기기도 한다.

2. 옵셔널 반환
상태 검사 메서드 이외에, 올바르지 않은 상태일 때 빈 `Optional` 혹은 `null` 같은 특수한 값을 반환하는 방법도 존재한다.

### 상태 검사 메서드, 옵셔널, 특정 값 중 하나를 선택하는 지침
- 외부 동기화 없이 여러 스레드가 동시에 접근할 수 있거나 외부 요인으로 상태가 변할 수 있다면 옵셔널이나 특정 값을 사용한다. 상태 검사 메서드와 상태 의존적 메서드 호출 사이에 객체의 상태가 변할 수 있기 때문이다.
- 성능이 중요한 상황에서 상태 검사 메서드가 상태 의존적 메서드의 작업을 일부 중복 수행한다면 옵셔널이나 특정 값을 선택한다.
- 다른 모든 경우엔 상태 검사 메서드 방식이 좋다. 가독성이 좋고, 잘못 사용했을 때 발견하기 쉽기 때문이다.(상태 검사 메서드 호출을 잊었다면 메서드는 예외를 던질것이다.) 옵셔널은 괜찮지만, 특정 값은 검사하지 않고 지나쳐도 발견하기 어렵다.

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

0 comments on commit 0bdad39

Please sign in to comment.