2009-11-10 2 views
1

일부 기존 코드가 수정 중입니다. 메서드가있는 Object를 가지고 doSomething()을 말할 수 있습니다. 이 메소드는, 특정의 assertion가 실패했을 때에 예외를 슬로우합니다. 그러나 새로운 요구 사항으로 인해 특정 시나리오에서 예외를 throw하지 않고 해당 방법을 진행하는 것이 좋습니다.여기 글로벌 상태를 사용하고 있습니까?이 작업을 수행하는 더 좋은 방법이 있습니까?

이제 예외를 무시해야하는 곳에서이 메서드를 직접 호출하지 않습니다. 이 doSomething()은 다른 많은 메소드에서 내부적으로 호출되는 감사 메소드와 비슷하며, method1(), method2() 등을 말합니다.

예외를 무시해야하는 곳에서는 method1), 이제 method1() 예외를 throw하지 않으려는. 그래서 method1()을 기본 인수 method1 (ignoreException = false)을 취하고 method1 (true)을 호출하도록 수정했습니다.

또한 추가 인수를 사용하기 위해 doSomething()을 수정했으며 method1은 ignoreException을 doSomething (ignoreException)으로 다시 전달합니다.

잠재적으로이 추가 인수를 취하기 위해 모든 메소드, method2, method3 등을 변경해야합니다.

이 코드를 보면 누군가가이 플래그를 전달하는 대신 클래스의 멤버 변수로 가져온 다음 method1()을 호출하기 전에 setter를 호출 할 수 있다고 제안했습니다. 내 개체가 obj라고 말한 다음해야합니다. obj.setIgnoreXXXException (true); obj.method1(); obj.setIgnoreXXXException (false);

이것은 전 세계적인 상태를 유지하는 것 같고 나던 것 같습니다. 하지만 인수를 전달하는 다른 방법도 서투른 것처럼 보입니다. 많은 부분을 변경해야합니다 (이 클래스에는 하위 클래스가 있고 일부 메서드는 가상이므로 일부를 수정해야합니다)

더 좋은 방법이 있습니까? 이. 레거시이기 때문에 단위 테스트가 없기 때문에 기존 코드를 많이 수정하고 싶지는 않습니다.

답변

4

당신은 분명히 멤버가 아닌 함수 인자로 이것을 수행해야합니다 - 체크를 무시할지 여부는 객체가 아닌 함수 호출의 속성입니다. 임시 조건이 당신에게 두 가지 주요 문제를 줄 것이다 개최 지속 상태를 사용

:

  • 예외 안전 - 함수가 처리되지 않은 예외가 발생하는 경우, 다음 코드는 "무시"플래그 세트를 떠날 것이다.
  • 재진입 - 재귀 적으로 함수를 호출하거나, 여러 스레드에서있을 수 있습니다 예기치 않은 결과
당신은 플래그를 재설정 소멸자를 사용하여 안전을 제외 할 수 있습니다

:

class IgnoreException 
{ 
public: 
    explicit IgnoreException(Object &o) : object(o) 
    { 
     object.setIgnoreException(true); 
    } 
    ~IgnoreException() 
    { 
     object.setIgnoreException(false); 
    } 
private: 
    Object &object; 
}; 

void callMethodOneIgnoringException(Object &object) 
{ 
    IgnoreException ignore(object); 
    object.method1(); 

    // the flag is restored here, even if an exception was thrown. 
} 

을 할 수 있습니다 ' 그것이 재진입 적이 지 않도록하십시오. 영속 상태에 액세스하는 모든 함수는 재진입 가능하지 않으므로 유일한 해결책은 함수 인수를 사용하는 것입니다.

+0

여기에주의 사항을 설명해 주셔서 고맙습니다. 함수 인수를 사용합니다. – Arvind

0

클래스에 정적 부울 변수를 지정하고, 부울을 사용자가 선택하는 값으로 설정할 수있는 해당 클래스의 정적 멤버를 지정하십시오. 이 정적 부울을 사용하여 예외를 던지는 것을 억제 할 수 있으며 기존 인터페이스를 수정할 필요없이 코드에서 설정할 수 있습니다.

0

일종의 래퍼 (클래스 또는 기능적 폐쇄 중 하나)를 만드는 경로를 사용할 수 있습니다. 그런 다음, 이미 가지고있는 클래스를 사용하는 변수를 정의 할 수 있습니다. 클래스의 사용을 감쌀 것이므로 관리 단계 중 일부를 피할 수 있습니다.

var wrapper = yourClass.WrapWithThrowOption(true); 
wrapper.method(); 

또는

var wrapper = wrapWithOption(true, method1); 
wrapper(); 

당신은 당신이 사용하고있는 언어를 표시하지 않았다, 그래서 그냥 의사 구문을 사용했다.

+0

언어가 C++ – Arvind

+0

관련 코드 (또는 이와 유사한 예제)를 게시 한 경우 아이디어를 설명하기위한 코드를 작성할 수 있습니다. –

1

또한 클래스 변수 대신 함수 매개 변수를 사용하는 것이 좋습니다. 당신은 어쩌면 일부 예외를 억제 ... 약간의 변화를 원하는 결정하는 경우에 이것은 또한 미래에 당신에게 더 많은 자유를 제공

method1(true); 
// true means do throw an exception? 
// do supress an exception? 

enum ExceptionSuppressionType 
{ 
    SUPPRESS_NO_EXCEPTIONS, 
    SUPPRESS_ALL_EXCEPTIONS 
}; 
method1(SUPPRESS_ALL_EXCEPTIONS); 
// I'm pretty sure this will suppress the exceptions. 

:

그러나, 나는 일반적으로 대신 부울의 열거를 사용하여 운영자 추천 , 또는 그들을 새로운 형태로 다시 던지십시오. 부울은 단지 두 가지 선택 만 할 수있는 무언가를 reprenting하는 데 매우 뛰어납니다. 그러나 리턴 값과 매개 변수의 범위는 종종 시간이 지남에 따라 커집니다.

관련 문제