프로그래머라면 예기치 않은 상황에 대비하기 위해 대비해야할 책임이 있습니다. 이는 깨끗한 코드와 오류 처리가 연관있다는 말입니다. 따라서 오류를 체계적으로 잘 정리할 필요가 있겠습니다.
옛날 프로그래밍 언어에는 예외를 제공하지 않아서 에러코드로 처리했다고 합니다. 문제가 발생하면 에러코드도 함께 확인했어야 했죠. 하지만, 이제는 다릅니다. 로직과 오류처리 코드를 분리할 수 있습니다.
이 구문을 사용하면 예외를 통해 로직이 실행되는 문제의 범위를 지정할 수 있습니다. try
구문에서 문제가 생기면 실행중단 후 catch
블록으로 로직을 옮길 수 있습니다.
트랜잭션과 비슷하다고 할 수 있겠습니다. 이 구문을 통해 프로그램의 상태를 일관성있게 유지하는 것이 목표이기 때문입니다. 그러므로 예외가 발생할 수 있는 로직은 try-catch-finally 구문 안에 배치하는 편이 좋습니다.
이 경우에는 assertRaises() 를 사용해서 TDD를 구현하면 되겠지요.
옛날 자바는 메소드 선언 시 메소드가 반환할 예외를 모두 열거했습니다. 메소드가 반환하는 예외는 메소드 유형의 일부였습니다. 코드가 메소드를 사용하는 방식이 메소드 선언과 맞지 않으면 컴파일도 못했다고 합니다.
그렇지만 확인된 예외를 사용하지 않게된 이유는 아래와 같습니다.
이 글들을 먼저 읽어보시는 것을 추천드립니다. Checked Exceptions v. Unchecked Exceptions 기본 설명 , Checked Exception이 꺼려지는 이유에 대한 국내 아티클 을 소개합니다.
정리해보자면 자바의 설계상 안전한 소프트웨어를 구현하기 위한 도구였으나 그렇게 되지 못했다 라고 이해했습니다.
예외를 던질때는 호출스택 뿐 아니라, 오류 메시지에 적절한 정보를 담을 필요가 있습니다. 가능하다면 앱이 로그를 찍어서 디버깅하기 편하기 만들어줍니다.
애플리케이션 단에서는 오류를 잘 잡을 궁리를 해야합니다.
외부 라이브러리에서 던지는 모든 에러를 메인 로직에서 모두 캐치하려고 할 것이 아니라, 호출하는 라이브러리를 감싸서 거기서 발생하는 모든 에러를 wrapping 하는 편이 훨씬 깔끔합니다. 이 기법의 장점은 아래와 같습니다:
상기 이야기대로 코드를 짜더라도, 로직 중단이 적합하지 않을 때가 있습니다. 이럴 땐 리팩토링에 나오는 SPECIAL CASE PATTERN이 적합합니다1.
null
을 리턴하지 마라악명높은 NullPointerException
이 어디서 터질지 캐치하기 힘든 로직을 짜지않기를 주문하는 글입니다. 대체 어디서 온 null
인지 알 수 없도록 코드를 짜지 않고, 이에 대한 해결책으로 앞서말한 SPECIAL CASE PATTERN을 다시 소개합니다.
null
을 전달하지 마라마찬가지로, null
을 메소드로 전달하는 것은 더 악질이라고 합니다. 진짜 어디서 문제가 발생할지 잡기 더 힘들 것으로 보입니다… 저자는 해결책으로 아래 내용을 소개합니다.
assert
구문을 사용해서 아예 Exception을 발생시킵니다.아예 null
을 못받도록 하는 것이 합리적이라고 합니다.
읽기 좋은 코드 뿐 아니라 안정성 있는 코드 또한 고려해야합니다. 오류처리를 프로그램 논리와 분리하여 관심사를 각각 분리하고 이를 통해 로직(에러든 본디 로직이든)에 집중할 수 있도록 합시다.