Pergunta

Quer saber quanto esforço eu deveria ir para forçar informações de depuração útil ao criar mensagens de exceção, ou devo apenas confiar em que o usuário forneça a informação certa, ou adiar a coleta de informações para um manipulador de exceção?

Eu vejo um monte de pessoas pessoas fazendo suas exceções como:

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

ou estender as exceções padrão com exceções personalizadas que não fazem muito, mas mudar o nome da exceção:

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

Mas isso não fornece muita depuração informações ... e não impõe qualquer tipo de formatação com a mensagem de erro. Então você pode acabar com exatamente o mesmo erro produzir duas mensagens de erro diferentes ... por exemplo, "conexão banco de dados falhou" vs "não foi possível conectar ao db"

Claro, se bolhas ao topo, ele vai imprimir o rastreamento de pilha, que é útil, mas nem sempre dizer-me tudo o que preciso saber e geralmente eu acabar por ter de começar a filmar fora var_dump () declarações para descobrir o que deu errado e onde ... embora este poderia ser um pouco compensado com um manipulador de exceção decente.

Eu estou começando a pensar em algo como o código abaixo, onde eu requerem o executante da exceção para fornecer argumentos necessários para produzir a mensagem de erro correta. Eu estou pensando que este pode ser o caminho a percorrer no que:

  • O nível mínimo de informação útil deve ser fornecida
  • Produz mensagens de erro pouco consistentes
  • Modelos para mensagens de exceção todos nos um local (classes de exceção), de modo mais fácil para atualizar as mensagens ...

Mas eu vejo o lado negativo é que eles são mais difíceis de uso (requer que você olhar para cima definição de exceção), e, portanto, pode desencorajar outros programadores de usar exceções fornecidos ...

Eu gostaria algum comentário sobre esta ideia, e as melhores práticas para um quadro de mensagem de exceção consistente e flexível.

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

Em seguida, usado como:

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

e nós pode fazer algo como um nl2br em um manipulador de exceção personalizada para fazer as coisas agradáveis ??para a saída de html.

leitura Já esteve: http://msdn.microsoft.com/en-us/library/cc511859. aspx #

E não há nenhuma menção de qualquer coisa assim, então talvez seja uma má idéia ...

Foi útil?

Solução

Eu recomendo fortemente os conselhos sobre de Krzysztof blogue e gostaria de observar que no seu caso você parece estar tentando lidar com o que ele chama de erros de uso.

Neste caso, o que é necessário não é um novo tipo para indicar isso, mas uma melhor mensagem de erro sobre o que causou isso. Como tal função auxiliar para qualquer um:

  1. gerar a corda textual para o lugar em exceção
  2. gerar toda a exceção e mensagem

É o que é necessário.

Abordagem 1 é mais clara, mas pode levar a um pouco mais detalhado uso, 2 é o oposto, trocando uma sintaxe terser por menos clareza.

Note que as funções devem ser extremamente seguro (que deve nunca, nunca causar uma exceção alheios a si mesmos) e não forçar o fornecimento de dados que é opcional em determinados usos razoáveis.

Ao usar qualquer um destes se aproxima de você torná-lo mais fácil para internacionalizar a mensagem de erro mais tarde, se necessário.

Uma pilha traço no mínimo dá-lhe a função e, possivelmente, o número da linha, portanto, você deve se concentrar no fornecimento de informações que não é fácil de trabalhar a partir daí.

Outras dicas

Eu não tira do aconselhar sobre blog de Krzysztof, mas aqui é uma maneira morto-fácil criar exceções personalizadas.

Exemplo:

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

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

O código por trás disso (o que eu pedi emprestado em algum lugar, desculpas a quem que foi)

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

Consulte como projetar hierarquias de exceção na blogue de Krzysztof Cwalina, um co-autor de "Diretrizes de design do Framework".

Nunca, nunca confiar em um usuário de 'fazer a coisa certa', e incluir informações para depuração. Se você quiser informações, você precisa reunir-lo sozinho e armazená-lo em algum lugar onde o seu acesso.

Além disso, como foi dito, se é difícil (er) para fazer algo, os usuários vão evitar fazê-lo, por isso novamente, não dependem de sua boa vontade e seu conhecimento do que eles precisam para enviar.

Este pensamento implica um método pelo qual você coletar as informações e registrá-lo, o que implica usando var_dump em algum lugar ().

Além disso, como dito por Mark Harrison, um botão que torna mais fácil para enviar uma mensagem de erro em algum lugar é fantástico para você e para os usuários. Isso torna mais fácil para eles para relatar um erro. Você (como o destinatário) recebo um monte de duplicatas, mas informações duplicadas é melhor do que nenhuma informação.

No entanto muitos detalhes que você adicionar, certifique-se e quer

  • torná-lo fácil de cortar e colar a coisa toda, ou
  • tem um botão que irá relatar o erro para eles
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top