오류 처리
오류 처리는 프로그램에 반드시 필요한 요소 중 하나일 뿐이다.
입력이나 디바이스가 실패할 수도 있기 때문이다.
내 생각엔 틀릴 수 없는 코드더라도 분명 가능성은 늘 존재한다.
여기저기 흩어진 오류 처리 코드로 인해 실제 코드가 하는 일을 파악하기가 어려울 수 있다.
오류 처리 코드로 인해 논리를 이해하기 어렵다면 깨끗한 코드가 아니다.
오류 코드보다 예외를 사용하라
Try-Catch-Finally 문부터 작성하라
try 블록에 들어가는 코드를 실행하면 어느 시점에서든 catch 블록으로 넘어갈 수 있다.
미확인 예외를 사용하라
함수1 -> 함수2 -> 함수3 -> 함수4(새로운 예외 발생)
이 때,
1) 함수3 부터 함수2, 함수1 까지 새로운 예외를 catch로 처리해야 하거나,
2) throw 키워드를 모두 붙여줘야 한다.
이러한 건 OOP의 OCP(개발-폐쇄 원칙)을 위반한다.
개방-폐쇄 원칙
객체는 확장에는 개발, 수정에는 폐쇄되어야 한다.
-> (하지만, 확인된 예외를 처리함으로써 어떤 예외인지 알아채기 쉽고, 보다 유지보수하기가 편리해지는 것 아닐까? 하는 생각이 든다)
예외에 의미를 제공하라
오류 메세지에 정보를 담아 예외와 함께 던진다.
실패한 연산 이름, 실패 유형 등...
오류가 발생한 원인과 위치를 더 찾기 쉬워진다.
호출자를 고려해 예외 클래스를 정의하라
정상 흐름을 정의하라
앞 절에서의 지침들을 따른다면 비즈니스 논리와 오류 처리가 잘 분리된 코드가 나온다.
/*
* 식비를 비용으로 청구했다면 직원이 청구한 식비를 총계에 더한다.
* 식비를 비용으로 청구하지 않았다면 일일 기본 식비를 총계에 더한다.
*/
//1번
try{
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e){
m_total += getMealPerDiem();
}
//2번
public class PerDiemMealExpenses implements MealExpenses{
public int getTotal(){
//청구값이 있다면 청구값을 반환
//청구값이 없다면 기본값을 반환
}
}
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
1번에서 2번으로 변경하게 되면 예외 상황을 처리할 필요가 없어진다.
null을 반환하지 마라
반환 타입이 nullable이라면 지속적으로 null check를 해야 한다.
만약 1번이라도 null check 코드가 빠졌다면 NPE가 발생한다.
nullable 타입을 반환하기보다 예외나 특수 사례 객체를 반환하라
외부 객체가 null을 반환한다면 감싸기 메서드를 구현해 예외를 던지거나 특수 사례 객체를 반환하라
//1번
List<Employee> employees = getEmployees();
if (employees != null){
for(Employee e : employees){
totalPays += e.getPay();
}
}
//2번
List<Employee> employees = getEmployees();
for(Employee e : employees){
totalPays += e.getPay();
}
굳이 null을 반환해야 할까?, 빈 리스트를 넘겨서 로직을 수행하지 않아도 되지 않은가?
이로써 쓸데없는 코드 2줄이 줄고, 보기에도 깔끔해졌다.
null을 전달하지 마라
메서드에서 null을 반환하는 방식도 나쁘지만, 메서드로 null을 전달하는 방식은 더 나쁘다.
대다수 프로그래밍 언어는 호출자가 실수로 null을 넘기면 적절히 처리하는 방법이 없다.
애초에 null을 넘기지 못하도록 금지하는 정책이 합리적이다.
인수로 null이 넘어오면 코드에 문제가 있다는 뜻이다.
결론
깨끗한 코드는 읽기도 좋아야 하지만 안정성도 높아야 한다.
이 둘은 상충하는 목표가 아니다.
오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다.
'스터디 > 클린코드' 카테고리의 다른 글
[Clean Code] 클린 코드(단위 테스트) - 14 (0) | 2021.03.09 |
---|---|
[Clean Code] 클린 코드(경계) - 13 (0) | 2021.03.09 |
[Clean Code] 클린 코드(객체와 자료 구조) - 11 (0) | 2021.03.09 |
[Clean Code] 클린 코드(형식맞추기) - 10 (0) | 2021.03.09 |
[Clean Code] 클린 코드(주석) - 9 (0) | 2021.03.09 |