programing

커스텀 예외 메시지:베스트 프랙티스

sourcejob 2022. 11. 3. 21:49
반응형

커스텀 예외 메시지:베스트 프랙티스

예외 메시지를 작성할 때 유용한 디버깅 정보를 강제하는 데 얼마나 많은 노력을 들여야 하는지, 아니면 사용자가 올바른 정보를 제공하도록 신뢰할 것인지, 아니면 예외 핸들러에 대한 정보 수집을 연기해야 하는지 궁금하십니까?

많은 사람들이 다음과 같은 예외를 두는 것을 볼 수 있습니다.

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

또는 사용자 정의 예외로 기본 예외를 확장하여 예외 이름을 변경합니다.

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

하지만 이것은 많은 디버깅 정보를 제공하지 않습니다.에러 메세지로 포맷을 실시하지 않습니다.따라서 정확히 동일한 오류가 발생하여 두 개의 다른 오류 메시지가 생성될 수 있습니다.예: "데이터베이스 연결에 실패했습니다" vs "DB에 연결할 수 없습니다"

물론 위에 버블이 있으면 스택트레이스가 인쇄되기 때문에 편리합니다만, 항상 필요한 모든 것을 알 수 있는 것은 아닙니다.보통 var_dump() 스테이트먼트를 실행해 무엇이 잘못되었는지, 어디에 문제가 있는지 알아내야 합니다.단, 이것은 적절한 예외 핸들러로 다소 상쇄될 수 있습니다.

아래의 코드와 같은 것을 생각하기 시작하고 있습니다.예외의 송신자가 올바른 에러 메시지를 작성하기 위해 필요한 arg를 제공하도록 요구합니다.내 생각엔 이렇게 하는 게 좋을 것 같아

  • 최소 수준의 유용한 정보를 제공해야 합니다.
  • 다소 일관된 오류 메시지 생성
  • 예외 메시지용 템플릿이 모두 한 위치(예외 클래스)에 있으므로 메시지를 쉽게 업데이트할 수 있습니다.

단, 사용법이 더 어렵기 때문에(예외 정의를 검색해야 하므로) 다른 프로그래머가 제공된 예외를 사용하지 못할 수 있습니다.

이 아이디어와 일관되고 유연한 예외 메시지 프레임워크에 대한 베스트 프랙티스에 대해 코멘트를 부탁드립니다.

/**
* @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
}

커스텀 예외 핸들러에서 nl2br과 같은 작업을 수행하여 html 출력에 적합합니다.

열람 내용 : http://msdn.microsoft.com/en-us/library/cc511859.aspx #

그리고 이런 건 언급이 없으니 안 좋은 생각일 수도 있어요

저는 Krzysztof의 블로그에 대한 조언을 강력히 추천하며, 당신의 경우 그가 말하는 사용 오류에 대처하려고 하는 것 같습니다.

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

  1. 예외에 넣을 텍스트 문자열을 생성하다
  2. 모든 예외와 메시지를 생성하다

그것이 필요한 것이다.

어프로치 1은 명확하지만 좀 더 자세한 사용법이 될 수 있습니다.2는 반대로 명확성이 떨어지는 테서 구문을 교환합니다.

함수는 매우 안전해야 하며(관련되지 않은 예외 자체를 발생시켜서는 안 되며), 특정 합리적인 용도로 선택 가능한 데이터를 강제로 제공해서는 안 됩니다.

이러한 방법 중 하나를 사용하면 나중에 필요에 따라 오류 메시지를 쉽게 국제화할 수 있습니다.

스택 트레이스에서는 적어도 함수와 회선번호를 알 수 있기 때문에, 그것으로부터 알기 어려운 정보를 제공하는 것에 초점을 맞출 필요가 있습니다.

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()}";
    }
}

Framework Design Guidelines의 공동 저자인 Krzystof Cwalina 블로그에서 예외 계층 설계 방법을 참조하십시오.

사용자가 '올바른 일을 한다'고 믿고 디버깅에 대한 정보를 포함해서는 안 됩니다.정보가 필요한 경우 직접 정보를 수집하여 접근 가능한 곳에 저장해야 합니다.

또, 전술한 바와 같이, 유저는 무엇을 하기 어렵다면, 그것을 회피하기 때문에, 재차 호의나 무엇을 보내야 하는지 아는 것에 의존하지 말아 주세요.

이러한 생각은 정보를 수집하고 기록하는 방법을 의미하며, 이는 어딘가에서 var_dump()를 사용하는 것을 의미합니다.

또한 Mark Harrison의 말처럼 오류 메시지를 쉽게 보낼 수 있는 버튼은 귀하와 사용자 모두에게 환상적입니다.그것은 그들이 오류를 쉽게 보고할 수 있게 해준다.수신자로서 많은 중복 정보를 얻을 수 있지만 정보가 없는 것보다는 중복되는 것이 좋습니다.

아무리 많은 세부사항을 추가해도,

  • 전체를 쉽게 잘라 붙여넣을 수 있습니다.
  • 오류를 보고하는 버튼이 있다

언급URL : https://stackoverflow.com/questions/628408/custom-exception-messages-best-practices

반응형