이 부분의 요약은 생각보다 간단하고 사례들이 중요했다.
다음과 같은 방식을 통해 코드를 깔끔하게 하고, 안정성을 높이는 걸 권장한다.
예외를 사용해라.
- 오류 코드는 코드를 복잡하게 한다. 예외를 이용하면 코드가 깔끔해진다.
- 예외가 발생하는 코드는 일단 try-catch로 시작해라
예외클래스
- 아래처럼 예외를 잡아 변환하는 감싸기 클래스로 예외클래스를 만들면 매우 편리하다.
- 외부 API를 사용하는 경우, 예외 클래스를 설정하고 그 안에 외부 API 클래스를 넣는다. 이 방법은 라이브러리 전환 시 의존성 최소화, 테스트 코드 작성의 편리함, 예외 처리를 통일할 수 있는 이점을 가진다.
// 오류를 형편없이 분류한 사례
ACMEPort port = new ACMEPort(12);
try{
port.open();
} catch (DeviceResponseException e) {
reportPortError(e);
} catch (ATM1212UnlockedException e) {
reportPortError(e);
} catch (GMXError e) {
reportPortError(e);
} finally {
...
}
// 사용 코드, reportError로 깔끔해졌다.
LocalPort port = new LocalPort(12);
try {
port.open();
} catch (PortDeviceFailure e) {
reportError(e);
logger.log(e.getMessage(), e);
} finally {
...
}
// 예외 클래스, 이 클래스에서 예외 처리를 한다.
public class LocalPort {
private ACMEPort innerPort;
public LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
public void open() {
try{
innerPort.open();
} catch (DeviceResponseException e) {
throw new PortDeviceFailure(e);
} catch (ATM1212UnlockedException e) {
throw new PortDeviceFailure(e);
} catch (GMXError e) {
throw new PortDeviceFailure(e);
}
}
...
}
* 예외 클래스를 선언함에 따라 사용 코드가 매우 깔끔해졌다. 재사용한다 생각하면, 확실히 기분 좋을 거 같다.
정상흐름을 정의해라.
- 특수 상황을 처리하는 예외때문에 코드가 복잡하고 어려워질 때가 있다.
- 이런 경우 특수 사례 패턴(SPEACIAL CASE PATTERN)를 통해 처리하면 좋다.
※ 특수 사례 패턴(SPEACIAL CASE PATTERN) : 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식이다. 리팩터링에서 나온다 하는 데 추후 읽어보고 추가 글을 적겠다.
try {
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
이 예시는 청구비용을 계산하는 예시이다. 식비를 비용 청구 하였으면(try) expense에 추가, 아니라면(catch) 일일 기본 식비에 더한다.
하지만, expenseReportDAO에서 항상 MealExpense 객체를 반환하고, 청구한 식비가 있을 경우 일일 기본 식비를 반환하는 MealExpense 객체를 반환하도록 설계를 수정하자. (DAO에서 항상 MealExpense를 반환하되 조건에 따라서 값이 바뀐다는 말이다.)
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
public class PerDiemMealExpenses implements MealExpenses {
public int getTotal() {
// 기본값으로 일일 기본 식비를 반환한다.
}
}
그러면 코드는 예외 없이 간단해진다.
null을 반환하지 마라 / 전달하지 마라.
- 만약 null을 반환하는 코드가 있다면, NullPointerException을 잡는 코드를 매번 넣어야한다.
- 만약 null 처리를 안 했다면, 코드는 null이 오는 상황에서 갑작스러운 에러를 발생시킨다.
- null을 함수의 인자로 전달하는 경우도 똑같다.
- 저자는 null을 넘기지 못하도록 금지하는 정책이 필요하다 한다.
'책과 강연 > 클린 코드' 카테고리의 다른 글
| 클린코드 9장 : 단위 테스트 (1) | 2023.12.29 |
|---|---|
| 클린 코드 8장 : 경계 (1) | 2023.12.29 |
| 클린코드 6장 : 객체와 자료구조 (0) | 2023.12.24 |
| 클린 코드 5장: 형식 맞추기 (0) | 2023.12.24 |
| 클린코드 4장 : 주석 (0) | 2023.12.24 |