원문: Effective Scala - Error Handling
스칼라는 예외 처리를 위한 기능을 제공하지만, 정확성이 요구되며 프로그래머가 직접 오류를 처리해야 하는 일반적인 오류들에는 사용하지 않는 것이 좋습니다. 스칼라의 예외 처리 기능을 사용하는 대신 이러한 오류를 명시적으로 감싸서 표현하세요. Option 클래스나 com.twitter.util.Try를 사용하는 것이 적합한 선택입니다. 이들은 타입 시스템을 사용하여 사용자가 적절히 오류를 처리하도록 보장합니다.
예를 들어, 저장소(repository)를 설계할 때 다음과 같이 API를 설계하고픈 유혹이 있을 수 있습니다.
trait Repository[Key, Value] {
def get(key: Key): Value
}
그러나 이러한 구현은 키에 해당하는 값이 없을경우 구현자가 예외를 던져야 합니다. 더 나은 접근 방식은 Option을 사용하는 것입니다.
trait Repository[Key, Value] {
def get(key: Key): Option[Value]
}
이 인터페이스는 저장소에 모든 키가 포함되지 않을 수 있음을 명확히 보여주며, 프로그래머가 누락된 키를 처리하도록 보장합니다. 또한 Option은 이러한 경우를 처리하기 위한 다양한 구현을 제공합니다. 예를 들어, getOrElse는 누락된 키에 대한 기본값을 제공하는 데 사용됩니다.
val repo: Repository[Int, String]
repo.get(123) getOrElse "defaultString"
Handling exceptions (오류 처리)
스칼라의 예외 메커니즘은 (자바와 다르게) checked exception이 아니므로, 컴파일러는 프로그래머가 가능한 예외 집합을 포괄적으로 처리했는지 정적으로 검사해주지 못합니다. 따라서 광범위하게 예외를 처리하는 것이 유혹적일 수 있습니다.
하지만 일부 예외는 치명적이므로(fatal) 이러한 예외를 처리(catch)해서는 안 됩니다.
try {
operation()
} catch {
case _ => ???
}
이러한 코드는 잘못된 코드로, 전파해야하는 치명적인 오류도 처리하게 됩니다. 대신에, com.twitter.util.NonFatal을 사용하여 치명적이지 않은 예외만 처리하세요.
try {
operation()
} catch {
case NonFatal(exc) => ???
}