Domanda

Mi chiedo quanto sforzo dovrei fare per forzare utili informazioni di debug durante la creazione di messaggi di eccezione, o dovrei semplicemente fidarmi che l'utente fornisca le informazioni giuste o rinvii la raccolta di informazioni a un gestore di eccezioni?

Vedo molte persone che fanno le loro eccezioni come:

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

o l'estensione delle eccezioni predefinite con eccezioni personalizzate che non fanno molto ma cambiano il nome dell'eccezione:

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

Ma questo non fornisce molte informazioni di debug ... e non impone alcun tipo di formattazione con il messaggio di errore. Quindi potresti finire con esattamente lo stesso errore producendo due diversi messaggi di errore ... ad es. & Quot; Connessione al database fallita " vs " Impossibile connettersi a db "

Certo, se bolle in alto, stamperà la traccia dello stack, il che è utile, ma non sempre mi dice tutto quello che devo sapere e di solito finisco per iniziare a sparare var_dump () dichiarazioni per scoprire cosa è andato storto e dove ... sebbene ciò possa essere in qualche modo compensato con un gestore di eccezioni decente.

Sto iniziando a pensare a qualcosa come il codice qui sotto, dove richiedo il lanciatore dell'eccezione per fornire gli argomenti necessari per produrre il messaggio di errore corretto. Sto pensando che questo potrebbe essere il modo di procedere in questo:

  • È necessario fornire un livello minimo di informazioni utili
  • Produce messaggi di errore in qualche modo coerenti
  • Modelli per i messaggi di eccezione tutti in un'unica posizione (classi di eccezione), quindi è più semplice aggiornare i messaggi ...

Ma vedo il rovescio della medaglia che sono più difficili da usare (è necessario cercare la definizione dell'eccezione) e quindi potrebbe scoraggiare altri programmatori dall'utilizzare le eccezioni fornite ...

Vorrei un commento su questa idea, & amp; migliori pratiche per un quadro di messaggi di eccezione coerente e flessibile.

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

Quindi usato come:

// 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 potremmo fare qualcosa come un nl2br in un gestore di eccezioni personalizzato per rendere le cose piacevoli per l'output html.

Ho letto: http://msdn.microsoft.com/en-us/library/cc511859. aspx #

E non si fa menzione di nulla del genere, quindi forse è una cattiva idea ...

È stato utile?

Soluzione

Consiglio vivamente i consigli sul il blog di Krzysztof e noterai che nel tuo caso sembra che tu stia provando a gestire quelli che chiama errori di utilizzo.

In questo caso ciò che è richiesto non è un nuovo tipo per indicarlo ma un messaggio di errore migliore su ciò che lo ha causato. Come tale funzione di supporto per:

  1. genera la stringa testuale da inserire nell'eccezione
  2. genera l'intera eccezione e il messaggio

È ciò che è richiesto.

L'approccio 1 è più chiaro, ma può portare a un uso un po 'più dettagliato, 2 è l'opposto, scambiando una sintassi più terser per meno chiarezza.

Si noti che le funzioni devono essere estremamente sicure (non dovrebbero mai e poi mai causare un'eccezione non correlata) e non forzare la fornitura di dati facoltativi in ??determinati usi ragionevoli.

Utilizzando uno di questi approcci, è più facile internazionalizzare il messaggio di errore in seguito, se necessario.

Una traccia dello stack ti fornisce almeno la funzione, e possibilmente il numero di riga, quindi dovresti concentrarti sulla fornitura di informazioni che non sono facili da elaborare.

Altri suggerimenti

Non toglierò il consiglio riguardo al blog di Krzysztof, ma ecco un modo estremamente semplice per creare eccezioni personalizzate.

Esempio:

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

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

Il codice dietro quello (che ho preso in prestito da qualche parte, si scusa con chiunque fosse)

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

Vedi Come progettare le gerarchie di eccezioni sul blog di Krzysztof Cwalina, coautore di "Framework Design Guidelines".

Mai e poi mai fidarsi che un utente "faccia la cosa giusta" e includa informazioni per il debug. Se desideri informazioni, devi raccoglierle tu stesso e memorizzarle in un luogo in cui siano accessibili.

Inoltre, come affermato, se è difficile (e) fare qualcosa, gli utenti eviteranno di farlo, quindi di nuovo, non dipendono dalla loro buona volontà e dalla loro conoscenza di ciò che devono inviare.

Questo modo di pensare implica un metodo attraverso il quale raccogliere le informazioni e registrarle, il che implica l'utilizzo di var_dump () da qualche parte.

Inoltre, come affermato da Mark Harrison, un pulsante che semplifica l'invio di un messaggio di errore da qualche parte è fantastico per te e per gli utenti. Rende facile per loro segnalare un errore. Tu (come destinatario) ricevi molti duplicati, ma le informazioni duplicate sono meglio di nessuna informazione.

Per quanto molti dettagli si aggiungano, sii sicuro e

  • semplifica il taglio e l'incollaggio del tutto, oppure
  • ha un pulsante che segnalerà l'errore per loro
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top