2 주차
목, 금 | Assignment #11
- 📚 7장. 오류처리
- ✔️ TIL
Try-Catch-Finally
문부터 작성하라 (p.132)try
블록에서 무슨 일이 생기든지 catch
블록은 프로그램 상태를 일관성 있게 유지해야 하기 때문에,try-catch-finally
문으로 시작하는 편이 낫다.try
블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다.try
블록의 트랜잭션 범위부터 구현하게 되므로 범위 내 트랜잭션 본질을 유지하기 쉬워진다.OCP
(Open Closed Principle)를 위반한다.catch
블록에서 새로운 예외를 처리하거나, 선언부에 throws
절을 추가해야 한다.throws
경로에 위치하는 모든 함수가 최하위 함수에서 던지는 예외를 알아야 하므로 캡슐화가 깨진다.catch
블록에서 오류를 기록하도록 충분한 정보를 넘겨줘야 한다.Wrapper 클래스
를 정의하여 오류 처리 코드까지 함수에 포함시키고, 해당 클래스를 통해 API를 호출하는 것이 좋다.public class LocalPort {
private ACMEPort innerPort;
public LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
public void open() {
try {
innerPort.open();
} catch (DeviceResponesException e) {
throw new PortDeviceFailure(e);
} catch (ATM1212UnlockedException e) {
throw new PortDeviceFailure(e);
} catch (GMXError e) {
throw new PortDeviceFailure(e);
}
}
}
Wrapper 클래스
를 정의하면 특정 업체가 API를 설계한 방식에 발목 잡히지 않는다.// 1) 문제가 되는 코드
try {
MealExpences expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal(); // 식비를 비용으로 청구했다면 직원이 청구한 식비를 총계에 더한다.
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem(); // 식비를 비용으로 청구하지 않았다면 일일 기본 식비를 총계에 더한다.
}
// 2) 해결 (특수 사례 코드 적용)
MealExpences expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
// ExpenseReportDAO를 고쳐 언제나 MealExpense 객체를 반환하도록 수정하면 됨.
// public class PerDiemMealExpenses implements MealExpenses
특수 사례 패턴(Special Case Pattern)
: 클래스를 만들거나 객체를 조작해 특수 사례를 처리하는 방식으로, 클래스나 객체가 예외적인 상황을 캡슐화해서 처리하므로 클라이언트 코드가 예외적인 상황을 처리할 필요가 없어진다.NULL
을 반환하지 마라 (p.138)null
을 반환하게 되면 호출자 코드에 null
을 체크하는 로직이 추가되고, 누락할 경우 오류가 발생하게 된다.null
을 반환하고자 한다면 예외를 던지거나 특수 사례 객체를 반환하는 방안으로 대체한다.List
가 비었다면 null
대신 Collections.emptyList();
리턴)NULL
을 전달하지 마라 (p.140)null
을 전달하는 것은 메소드에서 null
을 반환하는 것보다 더 나쁘다.null
을 매개변수로 받을 경우 InvalidArgumentException
예외를 처리하거나 assert
문을 사용하여 null
이 아님을 검증해야 하는데 이는 이전 코드보다 낫지 못하다.null
을 적절히 처리하는 방법이 없으므로 애초에 넘기지 못하도록 금지하는 정책이 합리적이며, 이를 준수하면 부주의한 실수를 저지를 확률도 적어진다.null
을 리턴하는 것이 오히려 빈 값을 리턴하는 것보다 명확하다고 느껴졌었는데 이번 챕터를 읽고 난 후 이러한 방식이 얼마나 많은 불필요한 null
체크 로직을 양산시키는지 깨닫게 되었다.