일정에 쫒겨 마구잡이로 개발을하다보면, 수많은 예외를 보기 마련이다. 이런 예외를 처리하기위해 에러 코드로 분기하기도하고 예외로 처리하기도하고 많은 방법들을 사용했지만, 뭐가 더 낫고 뭘 어째서 써야했는지에 고민하진 않았는데 그에 대한 가이드를 해주는 느낌이다.
확실히 null
핸들링에 대한 고민은 항상 하던 문제였다. 매번 로직에 null
검사를 하는 조건문을 쓰기도 번거로웠다. 7장에서 제안하는 방법들을 사용한다면 확실히 코드의 양도 줄고 퀄리티는 높아질 것 같다.
오류를 코드로 처리하게되면 코드의 가독성은 낮아지고 계층의 깊이는 심하게 높아진다.
public class DeviceController {
...
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 shut down");
}
} else {
logger.log("Invalid handle for: " + DEV1.toString());
}
}
...
}
매번 반환값을 검사해야하기 때문에 코드가 복잡해지고 조건문 내의 블록내에서 다음 코드를 진행해야 하기 때문에 계층도 깊어진다.
그리고 이런 처리는 개발자가 손수 작성해서 하는 것이기에 실수로 놓친다면 바로 프로그램이 뻗을 수 있다. 그렇기에 예외를 던지는 편이 낫다.
예외를 던지는 코드
public class DeviceController {
...
public void sendShutDown() {
try {
tryToShutDown();
} catch (DeviceShutDownError e) {
logger.log(e);
}
}
private void tryToShutDown() throws DeviceShutDownError {
DeviceHandle handle = gethandle(DEV1);
DeviceRecord record = retrieveDeviceRecord(handle);
pauseDevice(handle);
clearDeviceWorkQueue(handle);
closeDevice(handle);
}
private DeviceHandle gethandle(DeviceID id){
...
throw new DeviceShutDownError("Invalid handle for: " + id.toString());
}
...
}
⇒ 예외를 던지고 코드를 분리함으로써 각 개념을 독립적으로 살펴보고 이해할 수 있다.
먼저 강제로 예외를 일으키는 테스트 케이스를 작성 후 테스트를 통과하게 코드를 작성하는 방법.
그러면 자연스럽게 try 블록의 트랜잭션 범위부터 구현하게 되기에 범위 내에서 트랜잭션 본질을 유지하기 쉬워진다.