📘 클린 코드 북스터디 정리입니다
📚 도서: 로버트 C. 마틴 《Clean Code》
🧑💻 목적: 좋은 코드에 대한 감각과 습관을 익히기 위해
🗓️ 진행 기간: 2025년 5월 ~ 매주 2장
📚 도서: 로버트 C. 마틴 《Clean Code》
🧑💻 목적: 좋은 코드에 대한 감각과 습관을 익히기 위해
🗓️ 진행 기간: 2025년 5월 ~ 매주 2장
📖 [7장] 오류 처리
✅ 핵심 요약 (Key Takeaways)
이 장의 핵심 문장
깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 한다
저자가 전달하고자 하는 메시지 요약 (3~5줄)
- 깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 함
- 오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지며 코드 유지보수성도 크게 높아짐
- 예외 처리 시 호출자를 고려해야 함
💡 내용 정리
깨끗한 코드와 오류 처리의 연관성
- 깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 함
- 오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지고 코드 유지보수성도 향상
오류 코드보다 예외 사용
- 오류 플래그 설정이나 반환 방식은 호출자 코드를 복잡하게 만듦
- 예외를 던지면 오류 처리 코드와 논리를 분리할 수 있음
try-catch-finally 문부터 작성
- catch문을 사용하면 예외의 범위를 정의할 수 있음
- TDD에서 try 범위를 자연스럽게 먼저 고려하게 되어 트랜잭션 경계 설계가 쉬움
public List<RecordedGrip> retrieveSection(String sectionName) {
try {
FileInputStream stream = new FileInputStream(sectionName);
} catch (Exception e) {
throw new StorageException("retrieval error", e);
}
return new ArrayList<>();
}
// 리팩토링 가능
public List<RecordedGrip> retrieveSection(String sectionName) {
try {
FileInputStream stream = new FileInputStream(sectionName);
stream.close();
} catch (FileNotFoundException e) {
throw new StorageException("retrieval error", e);
}
}
미확인 예외(unchecked exception) 사용
- 확인된 예외는 OCP 위반 위험 → 실익을 따져 신중히 사용
- 최하위 함수가 새로운 예외를 던질 경우, 호출자 모두 수정 필요
예외에 의미를 제공하라
- 실패한 연산 이름, 실패의 전후 상황 등 의미 있는 메시지를 제공
호출자를 고려해 예외 클래스를 정의
- 예외 정의 시 가장 중요한 관심사는 "오류를 잡아내는 방법"
- 단일 예외로 처리 가능한 경우와, 분기처리 필요한 경우 구분
- 외부 라이브러리는 Wrapper로 감싸 추상화
try {
captureSpotService.getPhoto();
} catch (CustomException e) {
log.error("에러 발생", e);
return ErrorResponse.of("오류 발생");
}
try {
paymentService.charge();
} catch (CardDeclinedException e) {
return ResponseEntity.status(402).body("카드 거절됨");
} catch (NetworkTimeoutException e) {
return ResponseEntity.status(504).body("결제 서버 응답 없음");
}
정상 흐름을 정의하라 (Special Case Pattern)
- 예외 케이스를 객체로 캡슐화 → 클라이언트 코드 간소화
null 반환
- null 대신 예외 또는 특수 객체 반환
- 외부 API에서 null 반환 시, 감싸기 메서드로 처리
// 방법1
List<Employee> employees = getEmployees();
if (employees != null) {
for (Employee e : employees) {
totalPay += e.getPay();
}
}
// 방법2
List<Employee> employees = getEmployees();
for (Employee e : employees) {
totalPay += e.getPay();
}
public List<Employee> getEmployees() {
if (직원이 없다면) {
return Collections.emptyList();
}
}
null 전달
- null을 인수로 기대하지 않는 메서드에 전달하는 일은 지양
- null 허용이 아닌 경우 명시적으로 금지 정책을 유지
💡 인상 깊었던 문장 & 나의 인사이트
책에서 가장 기억에 남는 문장 1~2개 인용
오류를 분류하는 방법은 수없이 많다. 발생한 위치…(중략)…
하지만 오류를 정의할 때 프로그래머에게 가장 중요한 관심사는 오류를 잡아내는 방법이 되어야 한다
왜 인상 깊었는가
생각해보지 못한 생소한 관점이라 인상깊었다.
사실 오류가 발생하면 보통은 “어떤 오류인지”, “어디서 발생했는지”에만 집중하게 된다.
즉, 오류를 사후적으로 추적하고 대응하는 데 초점을 두는 것이다.
하지만
오류를 정의할 때 프로그래머에게 가장 중요한 관심사는 오류를 잡아내는 방법이 되어야 한다
는 문장은, 오류 처리 역시 설계의 일부로 보아야 한다는 메시지를 담고 있다.
오류가 발생한 후에 당황하며 원인을 쫓는 것이 아니라,
애초에 어떤 오류가 발생할 수 있는지를 정의하고,
그에 따라 예측 가능한 흐름과 복구 전략을 설계하라는 뜻이다.
결국 오류 처리는 ‘디버깅 포인트’가 아니라,
처음부터 설계에 포함되어야 할 요소라는 것이다.
🛠 실무 적용 아이디어 (To Action)
오늘부터 실천해볼 작고 구체적인 실천 1~2가지
- 오류 코드보다 예외 사용하기
- 외부 API 감싸기
- 예외의 정보 제공하기 (실패한 연산 이름, 실패 유형 등)
'북스터디 > 클린코드' 카테고리의 다른 글
| 09장 - 단위 테스트 (1) | 2025.06.03 |
|---|---|
| 08장 - 경계 (0) | 2025.05.29 |
| 06장 - 객체와 자료 구조 (0) | 2025.05.21 |
| 05장 - 형식 맞추기 (1) | 2025.05.20 |
| 04장 주석(Comments) (1) | 2025.05.18 |
댓글