Question

Vous vous demandez combien d’efforts je devrais faire pour forcer l’utilisation d’informations de débogage utiles lors de la création de messages d’exception, ou devrais-je simplement faire confiance à l’utilisateur pour fournir les bonnes informations, ou reporter la collecte des informations à un gestionnaire d’exceptions?

Je vois beaucoup de gens faire leurs exceptions comme:

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

ou étendre les exceptions par défaut avec des exceptions personnalisées qui ne font pas grand chose mais changent le nom de l'exception:

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

Mais cela ne fournit pas beaucoup d'informations de débogage ... et n'impose aucune forme de formatage avec le message d'erreur. Ainsi, vous pourriez vous retrouver avec exactement la même erreur et produire deux messages d'erreur différents ... Par exemple, "Connexion à la base de données ayant échoué". vs "Impossible de se connecter à la base de données"

Bien sûr, si elle bouillonne vers le haut, elle imprimera la trace de la pile, ce qui est utile, mais elle ne me dit pas toujours tout ce que j'ai besoin de savoir et, en général, je finis par devoir commencer à utiliser var_dump (). déclarations pour découvrir ce qui ne va pas et où ... bien que cela puisse être quelque peu compensé par un gestionnaire d'exception décent.

Je commence à penser à quelque chose comme le code ci-dessous, dans lequel je demande à le lanceur de l'exception de fournir les arguments nécessaires pour produire le message d'erreur correct. Je pense que cela pourrait être la voie à suivre:

  • Le niveau minimum d'informations utiles doit être fourni
  • Produit des messages d'erreur relativement cohérents
  • Modèles pour les messages d'exception tous situés dans le même emplacement (classes d'exception), facilitant ainsi la mise à jour des messages ...

Mais je vois un inconvénient: ils sont plus difficiles à utiliser (vous devez consulter la définition des exceptions) et pourraient donc décourager les autres programmeurs d'utiliser les exceptions fournies ...

Je voudrais commenter cette idée, & amp; Meilleures pratiques pour un cadre de messages d'exception cohérent et flexible.

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

Ensuite utilisé comme:

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

et nous pourrions faire quelque chose comme un nl2br dans un gestionnaire d'exceptions personnalisé pour rendre les choses agréables pour la sortie HTML.

Vous avez lu: http://msdn.microsoft.com/en-us/library/cc511859. aspx #

Et rien de ce genre n'est mentionné, alors c'est peut-être une mauvaise idée ...

Était-ce utile?

La solution

Je vous recommande fortement de donner votre avis sur le blog de Krzysztof . et notez que dans votre cas, vous semblez essayer de traiter ce qu’il appelle les erreurs d’utilisation.

Dans ce cas, ce qui est requis n’est pas un nouveau type pour l’indiquer, mais un meilleur message d’erreur concernant sa cause. En tant que telle, une fonction d’aide à:

  1. génère la chaîne textuelle à placer dans l'exception
  2. générer l'ensemble de l'exception et du message

Est ce qui est requis.

L’approche 1 est plus claire, mais peut conduire à un usage un peu plus verbeux, le 2 est l’inverse, échangeant une syntaxe plus économe que moins claire.

Notez que les fonctions doivent être extrêmement sûres (elles ne doivent jamais, elles-mêmes, provoquer une exception non liée) et ne pas forcer la fourniture de données facultative dans certaines utilisations raisonnables.

En utilisant l'une ou l'autre de ces approches, vous facilitez l'internationalisation du message d'erreur ultérieurement si nécessaire.

Une trace de pile au minimum vous donne la fonction et éventuellement le numéro de ligne. Vous devez donc vous concentrer sur la fourniture d'informations qui ne sont pas faciles à résoudre.

Autres conseils

Je ne vais pas oublier les conseils concernant le blog de Krzysztof, mais voici un moyen extrêmement simple de créer des exceptions personnalisées.

Exemple:

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

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

Le code derrière cela (que j'ai emprunté quelque part, excuses à qui que ce soit)

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

Voir Comment créer des hiérarchies d'exceptions à la page blog de Krzysztof Cwalina, coauteur des "Framework Design Guidelines".

Ne faites jamais confiance à un utilisateur pour "agir correctement" et incluez des informations pour le débogage. Si vous souhaitez des informations, vous devez les collecter vous-même et les stocker dans un endroit accessible.

Comme indiqué plus haut, s’il est difficile (ou difficile) de faire quelque chose, les utilisateurs éviteront de le faire. Par conséquent, ne vous fiez pas à leur bonne volonté et à leur connaissance de ce qu’ils doivent envoyer.

Cela implique une méthode permettant de collecter les informations et de les consigner, ce qui implique d'utiliser var_dump () quelque part.

En outre, comme l’a dit Mark Harrison, un bouton permettant d’envoyer facilement un message d’erreur est fantastique pour vous et pour les utilisateurs. Il leur est facile de signaler une erreur. En tant que destinataire, vous obtenez beaucoup de doublons, mais les informations en double valent mieux que pas d'information.

Quel que soit le détail que vous ajoutiez, assurez-vous de bien

  • facilite la découpe et le collage du tout, ou
  • avoir un bouton qui signalera l'erreur pour eux
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top