반응형
오류 코드보다 예외를 사용하라
오류 코드를 사용했을 때의 문제점
아래의 코드처럼 오류처리가 많아져 코드가 복잡해진다. 또한 휴먼에러 발생가능성이 농후해진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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());
}
}
...
}
|
cs |
따라서 아래와 같이 예외를 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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());
...
}
...
}
|
cs |
다만 c언어와 같이 언어에서 예외처리를 제공하지 않는 언어에서는 signal을 써서 처리하는 방법이 있다.
en.wikipedia.org/wiki/C_signal_handling
null을 반환하지 마라
null을 반환하게 되면 호출자에게 문제를 떠넘기는 것이다. 따라서 null을 확인하는 어지러운 코드가 붙게되고 만에하나 null체크를 하지 않아 exception이 발생하게 되는 경우 시스템 전체에 문제가 될 수도 있다.
[null을 반환하는 경우]
*항상 null체크를 해야 한다.
1
2
3
4
5
6
|
List<Employee> employees = getEmployees();
if (employee != null) {
for(Employee e : employees) {
totalPay += e.getPay();
}
}
|
cs |
[null을 반환하지 않는 경우]
1
2
3
4
5
6
7
8
9
10
11
12
|
List<Employee> employees = getEmployees();
for(Employee e : employees) {
totalPay += e.getPay();
}
public List<Employee> getEmployees() {
if ( /*.. 직원이 없을 경우 .. */)
return Collections.emptyList();
}
}
|
cs |
null을 전달하지 마라
당연한 이야기 이지만 사용하는 쪽에서는 null을 전달하면 안된다. 그러나 만약 null을 전달했을 때를 항상 대비해야하는데
클린코드에서는 두가지 방법을 제시한다.
1. 예외 던지기
1
2
3
4
5
6
7
8
9
10
|
public class MetricsCalculator {
public double xProjection(Point p1, Point p2) {
if(p1 == null || p2 == null) {
throw InvalidArgumentException(
"Invalid argument for MetricsCalculator.xProjection");
}
return (p2.x - p1.x) * 1.5;
}
} }
|
cs |
각 파라미터의 null상태를 확인하고 예외를 던진다.
2. assert 사용
1
2
3
4
5
6
7
|
public class MetricsCalculator {
public double xProjection(Point p1, Point p2) {
assert p1 != null : "p1 should not be null";
assert p2 != null : "p2 should not be null";
return (p2.x - p1.x) * 1.5;
}
}
|
cs |
클린코드에서는 assert가 더 좋은 방법이라고 설명한다. 그러나 내생각에는 시스템이 절대로 멈춰서는 안되는 상황이라면 assert보다는 exception을 던지는게 더 낫다고 생각된다. (물론 테스트가 완벽하게 되었다면 assert가 더 좋겠다!)
반응형
'좋은 코드 만들기 > 클린코드' 카테고리의 다른 글
[클린코드] 8. 경계 (0) | 2021.05.02 |
---|---|
[클린코드] 6. 객체와 자료 구조 (0) | 2021.04.25 |
[클린코드] 5. 형식 맞추기 (0) | 2021.04.11 |
[클린코드] 4. 주석 (0) | 2021.03.28 |
[클린코드] 3. 함수 (0) | 2021.03.21 |