경고! C ++ 프로그래머가 다른 언어에 관한 질문에 대답하려고 예외 처리를 어떻게 수행해야하는지에 대한 다른 생각을 가지고 여기에옵니다!
이 아이디어가 주어지면 :
예를 들어 HTTP 요청을 수행하고 검색된 데이터를 반환하는 인출 리소스가 있다고 가정합니다. 그리고 ServiceTemporaryUnavailable 또는 RateLimitExceeded와 같은 오류 대신 소비자에게 요청을 다시 시도하고 특정 실패에 신경 쓰지 말 것을 제안하는 RetryableError를 발생시킵니다.
... 내가 제안하는 한 가지는 코드의 일반성을 저하 시키거나 예외에 대해 많은 "번역 포인트"를 요구할 수있는 방식으로 오류를보고하는 것에 대한 우려를 행동 과정과 혼동 할 수 있다는 것입니다. .
예를 들어 파일로드와 관련된 트랜잭션을 모델링하면 여러 가지 이유로 실패 할 수 있습니다. 아마도 파일을로드하는 것은 사용자 컴퓨터에 존재하지 않는 플러그인을로드하는 것과 관련이 있습니다. 파일이 단순히 손상되어 파싱하는 동안 오류가 발생했을 수 있습니다.
어떤 일이 발생하든, 행동 과정은 사용자에게 일어난 일을보고하고 그에 대해 무엇을하고 싶은지 묻는 메시지 ( "다시 시도, 다른 파일로드, 취소")를 가정합니다.
던지는 사람 대 포수
이 과정은이 경우 어떤 종류의 오류가 발생했는지에 관계없이 적용됩니다. 구문 분석 오류의 일반적인 아이디어에 포함되지 않고 플러그인을로드하지 못하는 일반적인 아이디어에 포함되지 않습니다. 파일을로드하는 정확한 컨텍스트 (파일로드와 실패의 조합)에서 이러한 오류가 발생한다는 아이디어에 포함되어 있습니다. 따라서 일반적으로 나는 catcher's
예외가 아닌 (예 : 사용자에게 옵션을 묻는 메시지 표시) 응답에 대한 조치 과정을 결정 하는 책임으로 생각합니다 thrower's
.
달리 말하면, throw
예외 가 발생 하는 사이트는 일반적으로 이러한 종류의 상황 정보가 부족합니다. 특히 던지는 함수가 일반적으로 적용 가능한 경우. 이 정보가있을 때 완전히 퇴화되지 않은 상황에서도 복구 행동에 관한 정보를 throw
사이트 에 포함시킴으로써 스스로를 코너링하게 됩니다. catch
일반적으로 조치 과정을 결정하는 데 가장 많은 양의 정보가있는 사이트 인 사이트 는 해당 트랜잭션에 대해 해당 조치 과정이 변경되어야하는 경우 하나의 중앙 위치를 제공합니다.
더 이상 잘못된 것을보고하지 않고 예외를 처리하려고 할 때 예외 처리를 시작하면 코드의 일반 성과 유연성이 저하 될 수 있습니다. 구문 분석 오류가 항상 이런 종류의 프롬프트로 이어지는 것은 아니며, 예외가 발생하는 컨텍스트 (발생한 트랜잭션)에 따라 다릅니다.
맹인 던지는 사람
일반적으로 많은 예외 처리 설계는 종종 맹인 던지기의 아이디어를 중심으로 이루어집니다. 예외가 어떻게 발생하는지 또는 어디에서 발생하는지 알 수 없습니다. 수동 오류 전파를 사용하는 이전 형식의 오류 복구에도 동일하게 적용됩니다. 오류가 발생한 사이트에는 사용자 행동 과정이 포함되어 있지 않으며 최소한의 정보 만 포함하여 어떤 종류의 오류가 발생했는지보고합니다.
거꾸로 된 책임과 포수 일반화
이것에 대해 더 신중하게 생각하면서, 이것이 유혹이 될 수있는 일종의 코드베이스를 상상하려고 노력했습니다. 제 상상은 (아마도 잘못된 것입니다) 귀하의 팀은 여전히 여기에서 "소비자"의 역할을 수행하고 있으며 대부분의 호출 코드를 구현하고 있습니다. 아마도 여러분은 try
모두 동일한 오류 집합을 겪을 수 있는 많은 이질적인 트랜잭션 (많은 블록)을 가지고 있으며 디자인 관점에서 볼 때 균일 한 복구 조치 과정을 초래해야합니다.
Lightness Races in Orbit's
훌륭한 답변 의 현명한 조언을 고려할 때 (실제로 고급 라이브러리 지향 사고 방식에서 비롯된 것으로 생각됨) 트랜잭션 복구 사이트에 더 근접한 "할 일"예외를 던지려는 유혹에 빠질 수 있습니다.
여기서 "중요한 것"문제를 중앙 집중화하지만 여전히 잡기의 맥락에서 다루는 중개자, 일반적인 거래 처리 사이트를 찾을 수 있습니다.
이것은 모든 외부 트랜잭션이 사용하는 일종의 일반 함수를 디자인 할 수있는 경우에만 적용됩니다 (예 : 호출 할 다른 함수를 입력하는 함수 또는 복잡한 잡기를 수행하는이 중개 트랜잭션 사이트를 모델링하는 무시할 수있는 동작을 갖는 추상 트랜잭션 기본 클래스 ).
그럼에도 불구하고 다양한 오류에 대응하여 사용자의 행동을 중앙 집중화 할 책임이 있으며 여전히 던지기보다는 잡기의 맥락에 있습니다. 간단한 예 (Python-ish pseudocode, 나는 경험이 많은 Python 개발자가 아니기 때문에 이에 대한 관용적 인 방법이있을 수 있습니다) :
def general_catcher(task):
try:
task()
except SomeError1:
# do some uniformly-designed recovery stuff here
except SomeError2:
# do some other uniformly-designed recovery stuff here
...
[보다 좋은 이름으로 general_catcher
]. 이 예제에서는 수행 할 작업이 포함 된 함수를 전달할 수 있지만 관심있는 모든 유형의 예외에 대해 일반화 / 통합 잡기 동작의 이점을 얻을 수 있으며 "할 일"부분을 계속 확장하거나 수정하십시오. 당신은이 중심적인 위치를 좋아하지만 여전히 catch
이것이 권장 되는 상황에 있습니다. 무엇보다도, 우리는 던지는 장소가 "무엇을해야하는지"( "맹인 던지기"의 개념을 유지하면서) 자신에 대해 걱정하지 않아도됩니다.
여기에서 이러한 제안 중 어느 것도 도움이되지 않고 어쨌든 "무엇을해야하는지"예외를 던지려는 강한 유혹이 있다면, 이는 적어도 이것이 매우 반이 디오 적이며 일반화 된 사고 방식을 잠재적으로 낙담시킬 수 있다는 점에 유의하십시오.