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

[#71][2기] 필요없는 검사 예외 사용은 피하라 #342

Merged
merged 1 commit into from
Oct 25, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions 10장/71_필요_없는_검사_예외_사용은_피하라_김광훈.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Item 71. 필요없는 검사 예외 사용은 피하라
## 1. 핵심정리
- 꼭 필요한 곳에만 사용한다면, 검사 예외는 프로그램의 안정성을 높여준다. 하지만 남용하면 쓰기 어려운 API 를 낳는다.
- 예외 상황에서 복구할 방법이 없다면 `비검사 예외`를 던지자.
- 복구가 가능하고 호출자가 그 처리를 해주길 바란다면, 우선 옵셔널을 반환해도 될지 고민하자.
- 옵셔널만으로는 상황을 처리하기에 충분한 정보를 제공할 수 없을 때만 검사 예외를 던지자.

<br>

## 2. 검사 예외 (Checked Exception)
- 검사 예외는 발생한 문제를 프로그래머가 처리하여 안정성을 높힐 수 있다.
- 물론, 과하게 사용하면 오히려 쓰기 불편한 APi 가 될 수 있다.
- (1) try/catch 블록, throws
```java
public class Example {

public void example() {

try {

} catch (IOException e) {

}

try {

} catch (IOException e) {

}

try {

} catch (IOException e) {

}

...
}
}
```
- (2) Java 8, Stream
```java
public class Test {

public static void main(String[] args) {
String[] names = {"자바", "파이썬", "고", "Trigger"};

Arrays.stream(names)
.map(Example::verifyName) // <--- compile error
.collect(toSet());
}

public static class Example {

public String verifyName(String name) throws Exception {
if (name == "trigger") {
throw new Exception("fail");
}
return name;
}
}

}
```


<br>


## 3. 검사 예외를 회피하는 방법
### (1) Optional
- 검사 예외를 던지는 대신 단순히 빈 옵셔널을 반환하면 된다.
- 예시
- AS-IS
```java
Long userId = 1L;
try {
User user = userService.findUserById(userId);
} catch (Exception e) {
log.error("fail to find user, userId: {}", userId)
user = new User(userId);
}
```
- TO-BE
```java
Long userId = 1L;

User user = repository.findUserById(userId)
.orElseGet(() -> new User(userId));
```

<br>

### (2) 메서드를 두 개로 분할하여 비검사 예외로 바꾼다.
- 이 방식에서 첫 번째 메서드는 예외가 던져질지 여부를 boolean 값으로 반환한다.
- 예시
- AS-IS
```java
try {
obj.action(args);
} catch (TheCheckedException e) {
... // 예외 상황에 대처한다.
}
```
- TO-BE
```java
if(obj.actionPermitted(args)){
obj.action(args);
} else {
... // 예외 상황에 대처한다.
}
```

- 하지만 외부 요안에 의하여 상태가 변할 수 있다면, 이 방법은 적절치 않다.