본문 바로가기
공부 기록

[클린코드] 7장. 오류 처리

by 매트(Mat) 2024. 4. 19.

7장. 오류 처리

오류처리는 프로그램에 반드시 필요한 요소 중 하나이다. 오류처리는 프로그램 내의 코드가 여기저기 흩어져 있으면 실제 코드가 하는 일을 파악하기가 거의 불가능하다. 따라서 오류 처리 코드로 인해 프로그램 논리를 이해하기 어렵다면 클린코드라 부르기 어렵다.

오류코드보다 예외를 사용하라

오류코드를 사용하면 호출자 코드가 복잡해진다. 함수를 호출한 즉시 오류를 확인해야 하기 떄문이다. 그래서 오류가 발생하면 예외를 던지는 편이 낫다. (자바에서 예외처리는 던지거나(throws) 잡을 수 있다.(try-catch))

Try-Catch-Finally 문부터 작성하라

Try-Catch-Finally문을 통해 try 블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다. 자바에서는 catch를 이용하여 예외를 직접 처리할 수 할 수 있다. 따라서 예외로 인해 애플리케이션이 다운되거나 에러나는 것을 방지할 수 있다. (말 그대로 예외를 처리하는 것이다.)

언체크 예외를 사용하라

자바 프로그래머들은 체크 예외의 장단점을 놓고 논쟁을 벌여왔다. 체크 예외는 예외를 처리하지 않으면 컴파일 에러가 발생하여 좋은 예외로 생각하였다.

하지만 지금은 아니다. C#, C++, 파이썬, 루비는 체크 예외를 제공하지 않는다. 그럼에도 안정적인 SW를 개발할 수 있다.

그럼 체크예외의 단점이 뭘까? (사실 단점이 너무 크다.)

바로 OCP 원칙을 위반한다. 작은 시스템이면 그나마 괜찮지만 대규모 시스템의 경우 굉장히 치명적이다.

  • 최상위 함수가 아래 함수를 호출한다.
  • 아래 함수는 그 아래 함수를 호출한다.
  • 단계를 내려갈수록 호출하는 함수는 늘어난다.
  • 이제 최하위 함수를 변경해 새로운 오류를 던진다고 하자.
  • 체크예외를 던진다면 함수는 선언부에 throws을 추가해야 한다.
  • 그러면 변경한 함수를 호출하는 함수 모두를 throws을 추가해야 한다.

체크예외는 컴파일 시점에 예외를 확인할 수 있는 장점이 있지만 위처럼 캡슐화를 깨버리고, 모든 함수에 변경해야 하는 치명적인 단점 때문에 대부분 언체크 예외를 사용한다.

예외에 의미를 제공하라

애플리케이션 로깅 기능을 통해 catch 블록에서 오류를 기록하도록 충분한 정보를 넘겨주는 것이 좋다.

호출자를 고려해 예외 클래스를 정의하라

중복된 catch문으로 모든 예외를 잡는 것은 좋지 않다.

예외 클래스 직접 정의하여 해당 예외를 처리하자.

정상 흐름을 정의하라

결제 시스템 예를 들어보자.

  1. 사용자가 상품 결제를 했다.
  2. 단순히 변심으로 상품을 취소했다.

위 경우 애플리케이션은 예외처리를 해야할까?

그렇지 않다. 취소는 에러가 발생한 것이 아니라 상태를 변경한 것이다. 따라서 정상 흐름으로, 상태 값만 바꿔주면 된다.

따라서 사용자가 결제를 하고, 취소했다고 catch문으로 처리하면 안된다는 것이다.

null을 반환하지 마라

public void registerItem(Item item) {
    if (item != null) {
        ItemRegistry registry = persistentStore.getItemRegistry();
        if (registry != null) {
            Item existing = registry.getItem(item.getId());
        }
    }
}
  • 위 코드는 나쁜 코드다.
  • null 확인이 너무 많고 호출자에게 문제를 떠넘기는 것이다.
  • 따라서 누구라도 null 확인을 빼먹는다면 애플리케이션이 통제 불능에 빠질지도 모른다.
  • 해결법은 null을 반환시키지 않으면 된다.
public void registerItem(Item item) {
    ItemRegistry registry = persistentStore.getItemRegistry();
    Item existing = registry.getItem(item.getId());
}
  • 코드가 좀 더 깔끔해진 것을 볼 수 있다.

null을 전달하지 마라

  • 메서드에서 null을 반환하는 방식도 나쁘지만 null을 전달하는 방식은 더 나쁘다.
  • 따라서 null 전달은 최대한 피해야 한다.
  • null 전달은 애플리케이션 동작 조차 기대하기 어렵다.

결론

오류처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다. 또한 독립적인 추론이 가능해지며 코드 유지보수성도 크게 높아진다.

References

'공부 기록' 카테고리의 다른 글

[클린코드] 9장. 단위 테스트  (0) 2024.04.23
[클린코드] 8장. 경계  (0) 2024.04.22
[클린코드] 6장. 객체와 자료구조  (0) 2024.04.18
[클린코드] 5장. 형식 맞추기  (0) 2024.04.17
[클린코드] 4장. 주석  (0) 2024.04.16

댓글