Throw Design

예외 발생 지점 설계

throw는 단순히 빠져나가는 문장이 아니라 호출자에게 어떤 실패가 일어났는지 전달하는 인터페이스다. 타입과 메시지, 상태 보장이 함께 있어야 한다.

01

실패를 타입으로 분류한다

파일 포맷 오류와 범위 오류를 모두 runtime_error 문자열로만 구분하면 호출자가 정책을 만들기 어렵다.

02

커밋 전 검증한다

멤버 상태를 바꾸기 전에 입력을 검증하거나 임시 객체에 결과를 만든 뒤 교체한다.

03

맥락을 담는다

파일명, 줄 번호, 키 이름 같은 진단 정보를 메시지나 예외 타입에 포함한다.

domain error
입력 의미 오류 값은 읽었지만 도메인 규칙에 맞지 않는 경우다.
사용자 메시지와 연결된다.
out_of_range
경계 위반 인덱스, 포트 번호, 배열 범위를 벗어난 값을 표현한다.
표준 타입도 충분할 때가 많다.
nested
맥락 추가 하위 예외를 보존하면서 상위 문맥을 덧붙일 수 있다.
로그 품질이 좋아진다.
terminate
noexcept 위반 noexcept 경계 밖으로 예외가 나가면 종료된다.
던질 수 있는 호출을 안에 두지 않는다.

타입 구분 · 부분 변경 · 진단 점검

타입 구분 호출자가 다르게 처리해야 하는 실패가 같은 예외 타입으로 뭉개져 있지 않은가.
부분 변경 throw 전에 객체 상태 일부만 바뀌어 있지 않은가.
진단 오류 메시지만 보고 어떤 입력에서 실패했는지 좁힐 수 있는가.

맥락 있는 예외

if (line.empty()) {
    throw ParseError{path, lineNumber, "empty record"};
}