뭔가 잘못될 가능성은 늘 존재한다. 뭔가 잘못되면 바로 잡을 책임은 바로 우리 프로그래머에게 있다.

위와 같은 방법을 사용하면 호출자 코드가 복잡해진다. 함수를 호출한 즉시 오류를 확인해야 하기 때문이다. 그래서 예외를 던지는 편이 낫다.

먼저 강제로 예외를 일으키는 테스트 케이스를 작성한 후 테스트를 통과하게 코드를 작성하는 방법을 권장한다. 그러면 자연스럽게 try 블록의 트랜잭션 범위부터 구현하게 되므로 범위 내에서 트랜잭션 본질을 유지하기 쉬워진다.
checked 예외 는 컴파일 단계에서 확인되며 반드시 처리해야 하는 예외입니다.
(IOException, SQLException)
Unchecked 예외 는 실행 단계에서 확인되며 명시적인 처리를 강제하지는 않는 예외입니다.
(NullPointerException , IllegalArgumentException, IndexOutOfBoundException, SystemException)
메서드에서 확인된 예외를 던졌는데 catch 블록이 세 단계 위에 있다면 그 사이 메서드는 모두가 선언부에 해당 예외를 정의해야 한다.
즉 하위 단계에서 코드를 변경하면 상위 단계 메서드 선언부를 전부 고쳐야 한다는 말이다.
예외를 던질 때는 전후 상황을 충분히 덧붙인다.
다음은 오류를 형편없이 분류한 사례다.

위 경우는 예외에 대응하는 방식이 예외 유형과 무관하게 거의 동일하다.
그래서 코드를 간결하게 고치기가 아주 쉽다.

여기서 LocalPort 클래스는 단순히 ACMEPort 클래스가 던지는 예외를 잡아 변환하는 감싸기 클래스일 뿐이다.

이러한 감싸기 클래스는 매우 유용하다. 실제로 외부 API를 사용할 때는 감싸기 기법이 최선이다.

위의 코드는 나쁜 코드다. null을 반환하는 코드는 일거리를 늘릴 뿐만 아니라 호출자에게 문제를 떠넘긴다.
사용하려는 외부 API가 null을 반환한다면 감싸기 메서드를 구현해 예외를 던지거나 특수 사례객체를 반환하는 방식을 고려한다.
메서드로 null을 전달하는 방식은 더 나쁘다.
정상적인 인수로 null을 기대하는 API 가 아니라면 메서드로 null을 전달하는 코드는 최대한 피한다.
오류 처리를 프로그램 논리와 분리해 독자적인 사안으로 고려하면 튼튼하고 깨끗한 코드를 작성할 수 있다. 오류 처리를 프로그램 논리와 분리하면 독립적인 추론이 가능해지며 코드 유지 보수성도 크게 높아진다.