예외를 다시 던지면 추상화가 유출됩니까?


12

설명서에 특정 유형의 예외가 발생한다는 인터페이스 방법이 있습니다. 해당 메소드의 구현은 예외를 발생시키는 것을 사용합니다. 내부 예외가 발생하고 인터페이스 계약에 의해 선언 된 예외가 발생합니다. 다음은 더 나은 설명을위한 작은 코드 예제입니다. PHP로 작성되었지만 따르기가 매우 쉽습니다.

// in the interface

/**
 * @return This method returns a doohickey to use when you need to foo
 * @throws DoohickeyDisasterException
 */
public function getThatDoohickey();

// in the implementation

public function getThatDoohickey() {

    try {
        $SomethingInTheClass->doSomethingThatThrowsAnException();
    } catch (Exception $Exc) {
        throw new DoohickeyDisasterException('Message about doohickey failure');
    }

    // other code may return the doohickey

}

추상화가 누출되는 것을 막기 위해이 방법을 사용하고 있습니다.

내 질문은 : 이전 예외로 던져진 내부 예외를 전달하여 추상화를 유출합니까? 그렇지 않다면 이전 예외 메시지를 단순히 재사용하는 것이 적합합니까? 그것이 추상화를 누설한다면 왜 그렇게 생각하는지에 대한 지침을 제공 할 수 있습니까?

명확히하기 위해 내 질문에는 다음 코드 줄로 변경하는 것이 포함됩니다.

throw new DoohickeyDisasterException($Exc->getMessage(), null, $Exc);

누가 던지는 것이 아닌 원인 에 대한 예외는 있어야 한다 . 코드에을 가질 수 있으면 file_not_found을 던져야합니다 file_not_found_exception. 예외가해야 하지 라이브러리 구체적으로.
Mooing Duck

답변:


11

내 질문은 : 이전 예외로 던져진 내부 예외를 전달하여 추상화를 유출합니까? 그렇지 않다면 이전 예외 메시지를 단순히 재사용하는 것이 적합합니까?

대답은 "의존"입니다.

특히 예외와 그 의미에 따라 다릅니다. 본질적으로 다시 던지는 것은 인터페이스에 추가한다는 의미입니다. 직접 호출하는 코드를 작성한 경우 또는 예외의 브랜드 변경을 피하기위한 것입니까?

예외가 호출 된 코드에서 근본 원인에 대한 추적을 포함하여 추상화 외부에서 데이터를 유출 할 수는 있지만 일반적으로 예외는 호출자가 처리하기 때문에 받아 들일 수 있다고 생각합니다. 에서 나왔거나 사용자에게 표시되었으며 디버깅의 근본 원인을 알고 자합니다.

그러나 종종 예외를 허용하는 것은 추상화의 문제가 아닌 구현의 매우 합리적인 선택입니다. "내가 호출 한 코드가 그렇지 않은 경우 이것을 던지겠습니까?"


8

'내부'예외가 구현의 내부 동작에 대해 아무것도 알 경우 엄밀히 말하면, 당신은 있다 누출. 따라서 기술적으로 항상 모든 것을 잡아서 자신 만의 예외 유형을 던져야합니다.

그러나.

꽤 몇 가지 중요한 인자가 될 수 있습니다 에 대한 이. 가장 주목할만한 점 :

  • 예외는 예외입니다 . 그들은 이미 여러 가지 방법으로 '정상 작동'규칙을 위반하므로 캡슐화 및 인터페이스 수준 추상화도 위반할 수 있습니다.
  • UI 장벽 (정보 공개)을지나 내부 프로그램 정보를 유출하지 않는 한, 의미있는 스택 추적지점 간 오류 정보를 얻는 이점은 종종 OOP 정확성을 능가합니다.
  • 모든 내부 예외를 적절한 외부 예외 유형으로 감싸면 쓸모없는 상용구 코드 가 많이 생겨 예외의 전체 목적을 무효화 할 수 있습니다 (즉, 오류 처리 상용구로 일반 코드 흐름을 오염시키지 않고 오류 처리를 구현).

즉, 로그에 정보를 추가하거나 최종 사용자에게 내부 정보가 유출되는 것을 방지하기 위해 예외를 포착하고 줄 바꿈하는 것이 의미 있는 경우 많습니다 . 오류 처리는 여전히 예술적인 형태이므로 몇 가지 일반적인 규칙으로 정리하기가 어렵습니다. 일부 예외는 거품이 났고 다른 예외는 그렇지 않아야하며 결정은 상황에 따라 다릅니다. UI를 코딩하는 경우 사용자에게 필터링되지 않은 내용을 남기고 싶지 않습니다. 그러나 일부 네트워크 프로토콜을 구현하는 라이브러리를 코딩하는 경우 특정 예외를 버블 링하는 것이 옳은 일일 것입니다 (결국 네트워크가 다운 된 경우 정보를 향상 시키거나 복구 및 계속할 수있는 일이 거의 없습니다) 로 번역 NetworkDownException하는 FoobarNetworkDownException것은 의미가 없습니다.


6

우선, 여기서하는 일은 예외를 다시 던지는 것이 아닙니다. 다시 던지는 것은 문자 그대로 다음과 같은 예외를 던질 것입니다.

try {
    $SomethingInTheClass->doSomethingThatThrowsAnException();
} catch (Exception $Exc) {
    throw $Exc;
}

분명히 이것은 약간 의미가 없습니다. 다시 던지기는 스택을 버블 링하지 못하도록 예외를 중지하지 않고 일부 리소스를 해제하거나 예외 또는 원하는 다른 작업을 기록하려는 상황을위한 것입니다.

당신이 이미하고있는 일은 원인이 무엇이든간에 모든 예외를 DoohickeyDisasterException으로 바꾸는 것입니다. 당신이하려는 일이 아닐 수도 있습니다. 그러나이 작업을 수행 때마다 스택 추적에 유용한 경우를 대비하여 원래 예외를 내부 예외로 제안하고 전달하는 것이 좋습니다.

그러나 이것은 유출되는 추상화에 관한 것이 아니라 또 다른 문제입니다.

다시 던진 예외 (또는 실제로 포착되지 않은 예외)가 누수되는 추상화인지에 대한 질문에 대답하기 위해 호출 코드에 따라 다릅니다. 해당 코드에 추상화 된 프레임 워크에 대한 지식이 필요한 경우 해당 프레임 워크를 다른 프레임 워크로 바꾸면 추상화 외부에서 코드를 변경해야하기 때문에 누출이있는 추상화입니다.

예를 들어 DoohickeyDisasterException이 프레임 워크의 클래스이고 호출 코드가 다음과 같은 경우 누출이 추상화됩니다.

try {
    $wrapper->getThatDoohickey();
} catch (DoohickeyDisasterException $Exc) {
    echo "The Doohickey is all wrong!";
    echo $Exc->getMessage();
    gotoAHappyPlaceAndSingHappySongs();
}

타사 프레임 워크를 다른 예외 이름을 사용하는 다른 프레임 워크로 바꾸는 경우 이러한 모든 참조를 찾아서 변경해야합니다. 자체 예외 클래스를 만들고 프레임 워크 예외를 래핑하는 것이 좋습니다.

반면에 DoohickeyDisasterException이 자체 제작 중 하나라면 추상화를 유출하지 않을 것이므로 내 첫 번째 요점에 더 관심을 기울여야합니다.


2

내가 지나가려는 규칙은 다음과 같습니다. 마찬가지로 런타임 예외로 인해 버그가 생성 된 경우 일종의 DoHickeyException 또는 MyApplicationException이어야합니다.

의미하는 것은 오류의 원인이 코드 외부에 있고 오류가 예상되지 않으면 정상적으로 실패하고 다시 던져야한다는 것입니다. 마찬가지로 코드에 문제가 있으면 (잠재적으로) 사용자 정의 예외로 래핑하십시오.

예를 들어, 파일이 디스크에 있거나 서비스 를 사용할 수 있을 것으로 예상 되면 파일 을 정상적으로 처리하고 오류를 다시 발생시켜 코드 소비자가 해당 자원을 사용할 수없는 이유를 파악할 수 있도록하십시오. 어떤 유형에 대해 너무 많은 데이터를 만든 경우 줄 바꿈하는 것은 오류입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.