Log4KJS
Clean Code 정리 - 예외 처리 본문
입력이 잘못되거나, 네트워크 전송이 실패하는 등 무언가 잘못될 가능성이 언제나 존재하기 때문에, 예외 처리는 프로그래머가 반드시 수행해야 하는 요소 중 하나입니다. 클린 코드의 7장에서는 이러한 예외 처리를 함에 있어 지켜야할 원칙들을 소개합니다.
1. 오류 코드보다 예외를 사용하라
예외 처리(try.. catch.. finally) 를 지원하지 않는 언어를 생각해 봅시다. 예를 들어 C 를 이용해 프로그래밍할때 , 예외 처리는 보통
오류 코드를 반환하거나, 오류 플래그를 설정하는 방식이 일반적이었습니다. 이러한 방식은 몇가지 문제점을 가지고 있습니다.
- 함수의 로직과 상관 없는 플래그 인자, 리턴값 등이 코드에 나타난다.
- 함수를 호출한 직후 예외를 처리해야 한다. 따라서 호출자 코드에 로직과 오류 처리 코드가 뒤섞이며, 프로그래머가 오류 처리를 잊어버릴 확률이 존재한다.
클린 코드에서 제시하는 예제를 보면,
public void sendShutDown() {
DeviceHandle handle = getHandle(DEV1)
//디바이스 상태 점검 (예외처리)
if (handle != DeviceHandle.INVALID) {
//레코드 필드에 디바이스 상태 저장 (로직)
retrieveDeviceRecord(handle);
//일시정지되어 있는지 확인 (예외처리)
if (record.getStatus() != DEVICE_SUSPENDED) {
//디바이스 종료 (로직)
pauseDevice(handle);
clearDeviceWorkQueue(handle);
closeDevice(handle);
} else {
logger.log("Device suspended. Unable to shutdown");
}
} else {
logger.log("Invalid handle for: " + DEV1.toString());
}
}
로직 자체와는 관련이 없는 분기문을 이용해 예외를 처리하고 (심지어 두 층으로), 정상적인 로직과 예외에 대한 처리가 섞여 읽기 힘들어집니다. try... catch... finally 블럭을 제공하는 언어에서 이런 방식으로 예외를 처리하는 것은 옳지 못합니다.
public void sendShutDown() {
try {
tryToshutDown();
} catch (DeviceShutDownError e) {
logger.log(e);
}
}
public void tryShutDown() {
DeviceHandle handle = getHandle(DEV1);
DeviceRecord record = retrieveDeviceRecord(handle);
pauseDevice(handle);
clearDeviceWorkQueue(handle);
}
public void getHandle() {
...
throw new DeviceShutDownError("Invalid handle for: " + id.toString());
...
}
예외 처리 블럭을 사용하면 코드가 보기 좋아지고, 디바이스 종료 알고리즘과 오류 처리 알고리즘 (관심사) 를 분리할 수 있습니다.
2. Unchecked Exception 을 던져라
Checked Excpetion (try catch 를 강제하는 예외) 는 자바에만 존재하는 특이한 문법입니다. 장단점에 대해 많은 논쟁이 있어 왔지만, 확인된 예외라는 멋진 아이디어는 굳이 없어도 된다는 결론이 났다고 합니다. 그 이유는 Checked Exception 이 OCP (개방-폐쇄 원칙)을 위반하기 때문입니다.
개방-폐쇄 원칙이란 확장에는 열려있고, 수정에는 닫혀 있다는 뜻으로, 모듈을 수정하지 않고 새로운 코드를 작성함으로써 프로그램의 동작을 변경할 수 있어야 한다는 원칙입니다
아랫단 함수에서 throws 를 이용해 Checked Exception 을 던지면, 두 세단 위에 있는 catch 블럭까지 호출되는 모든 함수에 thows 키워드를 붙여줘야 하는데, 이는 전체 모듈의 수정을 불러옵니다.
3. 예외에 의미를 제공해라
예외를 던질 때에는 어떤 작업에서 예외가 발생하였는지, 실패 유형은 무엇인지에 대한 정보를 충분히 담아 던져야 합니다.
4. 예외는 호출자 입장에서 고려되어야 한다
호출자 입장에서 예외를 처리할 방법이 단일하다면, 던지는 예외의 종류 역시 단일한 것이 좋습니다.
예를 들어, 여러 타입에 대해 동일한 처리를 한다면, 해당 예외 타입들은 하나만 있어도 충분한 경우가 많습니다.
단, 특정 예외는 잡아내고 다른 예외는 무시해도 괜찮은 경우라면 여러 예외 클래스를 사용해야 합니다.
'Misc' 카테고리의 다른 글
| jstack, iostat, strace 정리 (1) | 2021.09.12 |
|---|---|
| Docker + Dockerfile 명령어 정리 (1) | 2021.08.07 |