오류 코드보다 예외를 사용하라
오류 코드를 사용했을 때의 문제점
아래의 코드처럼 오류처리가 많아져 코드가 복잡해진다. 또한 휴먼에러 발생가능성이 농후해진다.
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
C signal handling - Wikipedia
In the C Standard Library, signal processing defines how a program handles various signals while it executes. A signal can report some exceptional behavior within the program (such as division by zero), or a signal can report some asynchronous event outsid
en.wikipedia.org
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 |