문제

예외 메시지를 만들 때 유용한 디버깅 정보를 강요하는 데 얼마나 많은 노력을 기울여야하는지 또는 사용자가 올바른 정보를 제공 할 수 있도록 신뢰하거나 정보 수집을 예외 처리기에 연기해야합니까?

나는 많은 사람들이 다음과 같은 예외를하는 것을 봅니다.

throw new RuntimeException('MyObject is not an array')

또는 기본 예외를 사용자 정의 예외로 확장하는 것은 많지 않지만 예외의 이름을 변경합니다.

throw new WrongTypeException('MyObject is not an array')

그러나 이것은 디버깅 정보를 많이 제공하지 않으며 오류 메시지와 함께 어떤 종류의 형식도 시행하지 않습니다. 따라서 두 개의 다른 오류 메시지를 생성하는 동일한 오류로 끝날 수 있습니다 ... 예 : "데이터베이스 연결 실패"대 "DB에 연결할 수 없습니다"

물론, 그것이 상단에 거품이 나면, 그것은 스택 추적을 인쇄 할 것이지만, 그것은 유용하지만, 항상 알아야 할 모든 것을 말해주지는 않으며 일반적으로 var_dump () 문서를 촬영하기 시작해야합니다. 무엇이 잘못되었고 어디서 ... 이것은 괜찮은 예외 핸들러로 다소 상쇄 될 수 있습니다.

아래 코드와 같은 것에 대해 생각하기 시작했습니다. 필요하다 정확한 오류 메시지를 생성하기 위해 필요한 args를 제공하는 예외의 던지기. 나는 이것이 들어가는 길이라고 생각합니다.

  • 유용한 정보의 최소 수준을 제공해야합니다
  • 다소 일관된 오류 메시지를 생성합니다
  • 예외 메시지를위한 템플릿 한 위치 (예외 클래스)에있어 메시지를 업데이트하기가 더 쉽습니다 ...

그러나 나는 그들이 사용하기가 더 어렵다는 단점을 본다 (예외 정의를 찾아야 함). 따라서 다른 프로그래머가 제공된 예외를 사용하지 못하게 할 수있다 ...

이 아이디어에 대한 의견과 일관되고 유연한 예외 메시지 프레임 워크에 대한 모범 사례를 원합니다.

/**
* @package MyExceptions
* MyWrongTypeException occurs when an object or 
* datastructure is of the incorrect datatype.
* Program defensively!
* @param $objectName string name of object, eg "\$myObject"
* @param $object object object of the wrong type
* @param $expect string expected type of object eg 'integer'
* @param $message any additional human readable info.
* @param $code error code.
* @return Informative exception error message.
* @author secoif
*/
class MyWrongTypeException extends RuntimeException {
    public function __construct($objectName, $object, $expected, $message = '', $code = 0) {
        $receivedType = gettype($object) 
        $message = "Wrong Type: $objectName. Expected $expected, received $receivedType";
        debug_dump($message, $object);
        return parent::__construct($message, $code);
    }
}

....

/**
 * If we are in debug mode, append the var_dump of $object to $message
 */
function debug_dump(&$message, &$object) {
     if (App::get_mode() == 'debug') {
         ob_start();
         var_dump($object);
         $message = $message . "Debug Info: " . ob_get_clean();
    }
}

그런 다음 :

// Hypothetical, supposed to return an array of user objects
$users = get_users(); // but instead returns the string 'bad'
// Ideally the $users model object would provide a validate() but for the sake
// of the example
if (is_array($users)) {
  throw new MyWrongTypeException('$users', $users, 'array')
  // returns 
  //"Wrong Type: $users. Expected array, received string
}

또한 HTML 출력에 좋은 일을하기 위해 사용자 정의 예외 처리기에서 NL2BR과 같은 작업을 수행 할 수 있습니다.

읽었습니다 :http://msdn.microsoft.com/en-us/library/cc511859.aspx#

그리고 이와 같은 언급은 없으므로 아마도 나쁜 생각 일 것입니다 ...

도움이 되었습니까?

해결책

나는 조언을 강력히 추천합니다 Krzysztof의 블로그 그리고 당신의 경우 당신은 그가 사용 오류라고 부르는 것을 다루려고 노력하는 것 같습니다.

이 경우 필요한 것은 그것을 나타내는 새로운 유형이 아니라 원인에 대한 더 나은 오류 메시지입니다. 이러한 도우미 기능은 다음 중 하나입니다.

  1. 예외로 배치 할 텍스트 문자열을 생성하십시오
  2. 전체 예외와 메시지를 생성하십시오

필요한 것입니다.

접근 1은 더 명확하지만, 더 많은 장점 사용으로 이어질 수 있으며, 2는 반대이며, Terser 구문을 덜 명확하게하기 위해 거래합니다.

기능은 매우 안전해야하며 (관련된 예외를 일으키지 않아야 함) 특정 합리적인 용도에서 선택 사항 인 데이터 제공을 강요해서는 안됩니다.

이러한 접근 방식 중 하나를 사용하면 필요한 경우 나중에 오류 메시지를 더 쉽게 국제화 할 수 있습니다.

최소한의 스택 추적은 기능과 줄 번호를 제공하므로 그로부터 쉽게 해결하기가 쉽지 않은 정보를 제공하는 데 집중해야합니다.

다른 팁

Krzysztof의 블로그에 대한 조언을 방해하지는 않지만 여기에는 사용자 지정 예외를 만들 수있는 죽은 방법이 있습니다.

예시:

<?php
   require_once "CustomException.php";
   class SqlProxyException extends CustomException {}

   throw new SqlProxyException($errorMsg, mysql_errno());     
?>

그 뒤에있는 코드 (어딘가에 빌린 것, 그 사람에게 사과드립니다)

<?php

interface IException
{
    /* Protected methods inherited from Exception class */
    public function getMessage();                 // Exception message
    public function getCode();                    // User-defined Exception code
    public function getFile();                    // Source filename
    public function getLine();                    // Source line
    public function getTrace();                   // An array of the backtrace()
    public function getTraceAsString();           // Formated string of trace

    /* Overrideable methods inherited from Exception class */
    public function __toString();                 // formated string for display
    public function __construct($message = null, $code = 0);
}

abstract class CustomException extends Exception implements IException
{
    protected $message = 'Unknown exception';     // Exception message
    private   $string;                            // Unknown
    protected $code    = 0;                       // User-defined exception code
    protected $file;                              // Source filename of exception
    protected $line;                              // Source line of exception
    private   $trace;                             // Unknown

    public function __construct($message = null, $code = 0)
    {
        if (!$message) {
            throw new $this('Unknown '. get_class($this));
        }
        parent::__construct($message, $code);
    }

    public function __toString()
    {
        return get_class($this) . " '{$this->message}' in {$this->file}({$this->line})\n"
                                . "{$this->getTraceAsString()}";
    }
}

보다 예외 계층을 설계하는 방법 "프레임 워크 설계 지침"의 공동 저자 인 Krzysztof Cwalina의 블로그에서.

결코 사용자가 '올바른 일을하도록'신뢰하고 디버깅을위한 정보를 포함하지 마십시오. 정보를 원한다면 정보를 직접 모아 접근 가능한 곳에 보관해야합니다.

또한 언급 한 바와 같이, 무언가를하기가 어렵다면, 사용자는 그것을 피할 수 있으므로, 다시 한 번, 영업권과 그들이 보내야 할 것에 대한 지식에 의존하지 마십시오.

이 생각은 정보를 수집하고 로그인하는 방법을 암시하며, 이는 var_dump () 어딘가에 사용하는 것을 의미합니다.

또한 Mark Harrison의 말했듯이, 오류 메시지를 쉽게 보낼 수있는 버튼은 당신과 사용자에게 환상적입니다. 오류를 쉽게보고 할 수 있습니다. 귀하는 (수신자로서) 많은 복제를 받지만 중복 정보는 정보가없는 것보다 낫습니다.

그러나 당신이 추가하는 많은 세부 사항, 확실하고

  • 모든 것을 쉽게 자르고 붙여 넣을 수 있도록하거나
  • 오류를보고하는 버튼이 있습니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top