2012-04-13 2 views
4

현재 리펙토링을 시도하는 코드가 있습니다. 대규모 예외 집합에는 모든 예외에 대한 공통 코드와 특정 예외 유형별로 개별적으로 처리해야하는 특정 코드가 있습니다. 각 catch 블록에서 공통 부분을 없애는 방법을 알아 내려고 노력 중입니다. 한 가지 아이디어는 다음과 같이 수행하는 것입니다.예외의 공통 부분 처리하기

try { 
    /* Stuff that may fail */ 
} catch(const std::exception &) { 
    /* do common part here */ 
    try { throw; } 
    catch(const exception1 &) { 
    /* do stuff for exception1 here */ 
    } 
    catch(const exception2 &) { 
    /* do stuff for exception2 here */ 
    } 
} 

그러나 이것은 다소 추악합니다.

이 일반적인 논리를 제외하고 더 좋은 방법이 있습니까, 아니면 실제로이 시도를 피하기위한 이유가 있습니까?

답변

3

, try/catch 코드에 드문 드문 나타납니다 만한다 : 여기

다른 생각입니다. 문제는 예를 들어 catch 절에서 수행 된 작업이 조기 반납의 경우에도 수행되어야한다는 것입니다.

Idiomatic C++은 일반적으로 대부분의 작업을 제거하는 catch 절에서 정리가 필요한 상황을 피하기 위해 RAII를 광범위하게 사용합니다.

이제는 패턴이 그렇게 나쁘지 않습니다. 그 자체는이며, 일반적인 요소를 감안합니다. 그러나이 공통적 인 것들은 아마도 자동으로 처리 될 수 있습니다.

나는 모든 코드 기반에서 우연히 만났고, 단지 몇 시간 만 내가 클러치로 사용하지 말고 catch 절의 진정한 사용을 보았습니다.

3

예외의 큰 집합 함수 또는 방식으로, 공통 코드를 이동

일반적인 코드

있다. 각 catch에서 메소드를 호출하십시오. 다른 복제본을 삭제하는 것과 같습니다. try .. catch의 존재는 아무런 차이가 없습니다.


편집

하지만 "예외의 대형 세트"에 대한 정말 관심이 있다면, 진짜 문제는 예외의 큰 세트를 가지고있을 수 있습니다. 왜 다른 예외가 다른 처리를 필요로합니까? 예외는 실제로 예외적 인 경우에만 이벤트에 사용됩니까?

+2

이것은 내가 지금 가지고있는 것과 매우 유사합니다 (코드에서, 질문에 없습니다). 그러나 이것은 각 예외에서이 메서드에 대한 호출을 가지게 될 것이고 나중에 누군가 예외를 추가하고 혼란을 피하는 것을 잊어 버린다는 것을 의미합니다. 이 버그는 오랜 시간 동안 눈에 띄지 않을 수 있습니다. 왜냐하면 그 조건은 매우 예외적이어서 매우 드물게 처리되기 때문입니다. 따라서 나는 나중에 개발자들에게 이것을 안전하게 유지할 수있는 좋은 방법을 찾고있다. – LiKao

+0

"누군가 나중에 예외를 추가하고 호출을 잊어 버린 경우"그러나 해당 비평은 사용하는 모든 체계에 적용됩니다. 나중에 프로그래머가 잘못 변경했을 수 있습니다. 공통 코드가 함수로 추상화되는 경우, 나중에 프로그래머가 모든 'catch'에 대해 함수를 호출해야한다는 것이 매우 분명합니다. – Raedwald

+0

예, 어떤 계획을 잘못 변경하는 것이 가능하다는 데 동의합니다. 그러나 나에게있어서의 질문은 무엇인가 잘못된 것을 얻는 것이 얼마나 쉬운가하는 것입니다. 코드를 다른 상태로 유지하면서 다른 예외 사례를 추가 할 수 있다면 잘못 이해하기가 어렵습니다. 예외를 추가 할 수 있기 전에 특별한 것을 알아 내야 만한다면 사람들이이를 놓칠 수 있습니다. 어떤 경우에는 적극적으로 무언가를 변경함으로써 물건을 깰 수 있습니다. 다른 경우에는 무언가를 잊어서 물건을 엉망으로 만들 수 있습니다. 두 번째 경우는 대개 IMHO입니다. – LiKao

0

나는 공통 코드를 함수로 옮기기 만 할 것이다. 일반적으로

try { 
    /* Stuff that may fail */ 
} catch(const std::exception & e) { 
    /* do common part here */ 
    if (const exception1 * e1 = dynamic_cast<const exception1*>(&e) { 
    /* do stuff for exception1 here */ 
    } else if (const exception2 * e2 = dynamic_cast<const exception2*>(&e) { 
    /* do stuff for exception2 here */ 
    } else 
    throw; 
} 
+0

당신의 솔루션 중 어느 것도 매우 훌륭한 코딩 방법입니다. 많은 사람들은 예외 처리를 이해하지 못하므로 간단하게 유지하십시오. 귀하의 "특별"취급은 잘 이해되지 않을 것이며 올바르게 유지되지 않을 것입니다. –

관련 문제