7장. 오류 처리
[CleanCode] 7장 - Error Handling
Overview
*프로그램이 잘못될 가능성은 늘 존재한다. 그 원인은 **Error(오류)*이다.
김모씨의 말을 빌리자면,,

Error & Exception in Runtime
Error (오류)
시스템이 종료되어야 할 수준의 심각한 상황 (프로세스 종료)
미리 예측하여 방지 불가
ex) OutOfMemoryError, StackOverflowError
Exception (예외)
개발자가 구현한 로직에서 발생하거나 사용자에 의해 발생
개발자가 미리 방지 가능
상황에 맞는 Exception Handle을 해야한다.

Exception Class
Throwable
Error / Exception에 대한 메세지를 담고, Chained Exception에 대한 정보들을 기록
The
Throwableclass is the superclass of all errors and exceptions in the Java language. Only objects that are instances of this class (or one of its subclasses) are thrown by the Java Virtual Machine or can be thrown by the Javathrowstatement. Similarly, only this class or one of its subclasses can be the argument type in acatchclause. For the purposes of compile-time checking of exceptions,Throwableand any subclass ofThrowablethat is not also a subclass of either[RuntimeException](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/RuntimeException.html)or[Error](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Error.html)are regarded as checked exceptions …Throwable(String message, Throwable cause)
Java
Kotlin
호출한 곳에 Exception 발생 여부 통보
오류 코드보다 예외를 사용하기
🌱 로직과 Exception 처리를 분리하기
로직과 오류 처리 코드가 뒤섞여 있다.
오류를 발견하면 예외를 던진다.
Try-Catch-Finally
try-catch-finally
숫자를 0으로 나누면,,
예외 처리
예외가 발생하더라도 반드시 실행되어야 한다면,,
[Q] try-catch와 return 값
어떤 구문에 있는 값이 반환될까?
return 값을 조작?
메모리에 직접 접근한다면
finally 에서의 리턴은 자제하자
파일이 없으면 예외를 던지는지 알아보는 단위 테스트
아래 코드는 테스트가 성공할까?
Exception을 던지자
예외 유형을 좁히자
ex)
runCatching
kotilnx.runCatching
Exception은 크게 3가지 형태로 처리 가능
회피 : 호출한 쪽으로 그대로 전달 (throw)
복구 : 복구 또는 무시 가능한 경우에 catch 블럭 내에서 처리하거나 예외상황 처리후 에러 코드 반환
전환 : 특정 Exception으로 변환하여 전달 (throw)
Unchecked Exception을 사용하기

CheckedException단순 예외, 즉 컴파일 시 발생하는 Exception
프로그램 작성 시 이미 예측 가능
반드시 예외처리 해야함
UnCheckedException프로그램 실행시 발생하는 Runtime Exception
명시적 처리를 요구하지 X
RuntimeException을 상속받는 Exception → Unchecked Exception
Kotlin의 모든 Exception은 Runtime Exception을 상속받는다.
UnCheckedException을 사용해보자
Checked Exception을 사용해보면?
컴파일 오류
예측 가능한 CheckedException → 예외처리 강제
컴파일 오류를 막기위한 예외 처리
sayNickname 메서드에서 예외 발생 & 예외 처리 모두 하는 것?
sayNickname을 호출한 곳에서 예외 처리를 한다면? ✨
sayNickname에서 예외 처리 vs main에서 예외처리
Exception을 처리하는 위치는 중요하다.
in Clean Code,,
Checked Exception은 비용이 있다!
🌱 Checked Exception은 **OCP(Open-Closed Principle)를 위반한다.**
단순 출력 로직
출력을 안하는 Exception을 던질 때
하위 단계 코드 변경 → 상위 단계 코드 변경
모두
catch블록에서 처리선언부에
throws절 추가
🌱 Checked Exception은 **캡슐화를 깰 수 있다.**
Exception에 의미를 제공하기
🌱 오류가 발생한 **원인과 위치**를 찾을 수 있어야 한다.
stacktrace 활용
message에 유의미한 정보를 담아서 던지기
실패한 연산 이름, 실패 유형 언급
Logging 가능 → catch 블록에서 오류 기록
Exception Class 정의하기
호출자(Caller)를 고려해서 Exception을 정의할 수 있다.
정상 흐름을 정의하기
총계를 계산하는 로직
식비를 비용으로 청구 → 청구한 식비를 더함
청구 X → 일일 기본 식비를 더함
특수한 Exception이 있을 상황이 아니다.
DAO를 수정 → 항상 MealExpense 객체를 반환
Special Case Pattern (특수 사례 패턴)
클래스 or 객체를 조작해서 특수한 사례를 처리
클래스 내에서 예외적인 상황을 캡슐화
Null을 반환하지도, 전달하지도 마라
Null 반환
null 반환 대신 예외를 던지기
특수 Wrapper 객체로 감싸서 반환
직원 리스트를 가져와서 총 급여를 구하는 로직
null 반환 대신 빈 리스트를 반환하기
Null 전달
메서드가 null을 반환하는 방식도 나쁘지만, 메서드에 null을 전달하는건 더 나쁘다.
두 지점 사이의 거리를 구하는 메서드
인수로 null을 전달하면?
예외를 만들어 던지기
Exception을 잡아내는 처리기가 필요
assert
여전히 오류 발생
🌱 *애초에 null을 넘기지 못하게 하라*
결론
명시적 Exception은 반드시 이름을 지정하여 catching
어플리케이션에서 구현한 함수 내에서 Exception 발생이 예상되는 경우
최상위 Exception 클래스에서 반드시 catch 처리
Exception을 처리하는 궁극적인 위치가 중요.
Exception 발생시에는 Crashlytics 와 같은 에러 로그 라이브러리 등을 이용하여 개발자가 인지할 수 있도록 하기
Last updated