클린코드 - 오류,예외처리
예외가 발생항수있는 코드는 try-catch 블록을 써야한다.
확인된 예외는 컴파일단계에서 확인되는 FileNotFount 에러 같은것이다.
코드의 문제가 아닌 참조한 파일이없다던지 같이 환경의 문제이다.
미확인된 예외는 런타임단계에서 확인되는 코드 문제들이다.
확인된 예외를 사용하는경우 최 하휘함수에서 예외가 발생할떄
그것을 호출하는 상위 함수 와 그상위함수들 모두 catch 블록으로 예외를 처리해줘야한다.
확인된 예외는 Open Closed Principle 을 위반한다.
ACMEport port = ACMEPort(12); ///외부라이브러리
try{
port.open();
} catch(DeviceResponseException e){
reportPortError(e);
} catch(ATM1212UnlockedException e){
reportPortError(e);
} finally{
...
}
위 함수에서 reportPortError(e); 는 계속 중복될것이다.
외부 라이브러리 에서 어떤 예외가 나올지에 대해 다 처리한 경우인데
외부 라이브러리를 클래스로 감싸서 예외처리를 해주는게좋다.
프로그램과 외부라이브러리의 의존성이 줄기 떄문이다.
class LocalPort{
private ACMEport innerPort;
LocatlPort(int portNumber){
innerPort = ACMEPort(portNumber);
}
void open(){
try{
innerPort.open();
}catch (DeviceResponseException e){
throw PortDeviceFailure(e);
}catch(ATM1212UnlockedException e){
throw PortDeviceFailure(e);
}finally{
...
}
}
이런식으로 비즈니스논리와 오류처리를 분리된것이 좋다.
try{
MealExpensed expenses = expensesReportDAO.getMeals(employee.getId();)
total += expenses.getTotal(); // 비용정보가 있으면 총계 더함
} catch(MealExpensesNotFound e){
total += getMealPerDiem(); //비용정보없으면 예외처리해 기본식비만 더함
}
위 코드처럼 예외처리해서 비용정보가없을때 처리하는 거보다
비용정보가 없으면 기본식비를 리턴해주는 함수를 비즈니스로직에서 구현해주는게 좋다.
void registerItem(Item item){
if(item!=null){
ItemRegistry registry = persistentStore.getItemRegistry();
if(registry !=null){
Item existing = registry.getItem(item.getId());
}
}
}
위처럼 null 을 반환한다면 계속 아래 코드가 null 체크해주면서 일거리를 넘긴다.
계속 호출자에거 일거리를 주는격이다.
null 대신 특수객체나 예외를 던지는게좋다.
List employees = getEmployees();
if(employees!=null){
employees.map((e){
total += e.getPay();
});
}
위 처럼 getEmployees() 에서 null 을 반환하는것보다.
빈 List 를 반환했다면 더 깔끔할것이다.
null을 전달하는거도 나쁘다.
MealExpensed expenses = expensesReportDAO.getMeals(null)
이렇게 null 을 전달한경우 에러가 발생할것이다.
이런경우 getMeals() 함수에서 null 이 전달되면 예외를 throw 해주던지
assert 를 사용해서 실행을 막을수있다.