Sie fragen sich, wie viel Aufwand ich betreiben sollte, um nützliche Debugging-Informationen beim Erstellen von Ausnahmemeldungen zu erzwingen, oder ob ich dem Benutzer nur vertrauen soll, dass er die richtigen Informationen bereitstellt, oder die Erfassung von Informationen an einen Ausnahmehandler verschieben soll?
Ich sehe viele Leute, die ihre Ausnahmen machen wie:
throw new RuntimeException('MyObject is not an array')
oder Erweitern der Standardausnahmen um benutzerdefinierte Ausnahmen, die nicht viel bewirken, aber den Namen der Ausnahme ändern:
throw new WrongTypeException('MyObject is not an array')
Dies liefert jedoch nicht viele Debugging-Informationen ... und erzwingt keinerlei Formatierung mit der Fehlermeldung. Es könnte also zu genau demselben Fehler kommen, der zwei verschiedene Fehlermeldungen hervorruft ... z. B. "Datenbankverbindung fehlgeschlagen" vs "Verbindung zu Datenbank konnte nicht hergestellt werden"
Sicher, wenn es nach oben sprudelt, wird die Stapelverfolgung gedruckt, was nützlich ist, aber es sagt mir nicht immer alles, was ich wissen muss, und normalerweise muss ich anfangen, var_dump () -Anweisungen abzuschießen, um sie zu entdecken Was ist schief gelaufen und wo ... obwohl dies mit einem anständigen Ausnahmebehandler etwas ausgeglichen werden könnte.
Ich fange an, über so etwas wie den Code unten zu denken, wo ich erfordern den Werfer der Ausnahme notwendig args zuzuführen , um die richtige Fehlermeldung zu erzeugen. Ich denke, dies könnte der richtige Weg sein:
- Es muss ein Mindestmaß an nützlichen Informationen angegeben werden
- Erzeugt etwas konsistente Fehlermeldungen
- Vorlagen für Ausnahmemeldungen an einem Ort (Ausnahmeklassen), damit die Nachrichten einfacher aktualisiert werden können ...
Aber ich sehe den Nachteil darin, dass sie schwieriger zu verwenden sind (erfordert, dass Sie die Ausnahmedefinition nachschlagen) und daher andere Programmierer davon abhalten können, mitgelieferte Ausnahmen zu verwenden ...
Ich möchte einen Kommentar zu dieser Idee und zu Best Practices für ein konsistentes, flexibles Framework für Ausnahmemeldungen.
/**
* @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();
}
}
Dann verwendet wie:
// 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
}
und wir könnten so etwas wie ein nl2br in einem benutzerdefinierten Ausnahmebehandler tun, um die Dinge für die HTML-Ausgabe schön zu machen.
Gelesen: http://msdn.microsoft.com/en-us/library/cc511859.aspx#
Und so etwas wird nicht erwähnt, also ist es vielleicht eine schlechte Idee ...
RuntimeException::__construct()
Antworten:
Ich kann den Rat auf Krzysztofs Blog nur empfehlen und möchte darauf hinweisen, dass Sie in Ihrem Fall anscheinend versuchen, mit dem umzugehen, was er als Nutzungsfehler bezeichnet.
In diesem Fall ist kein neuer Typ erforderlich, um dies anzuzeigen, sondern eine bessere Fehlermeldung darüber, was ihn verursacht hat. Als solche Helferfunktion entweder:
Ist was erforderlich.
Ansatz 1 ist klarer, kann aber zu einer etwas ausführlicheren Verwendung führen. 2 ist das Gegenteil und tauscht eine Terser-Syntax gegen weniger Klarheit.
Beachten Sie, dass die Funktionen äußerst sicher sein müssen (sie sollten niemals selbst eine nicht verwandte Ausnahme verursachen) und nicht die Bereitstellung von Daten erzwingen müssen, die bei bestimmten angemessenen Verwendungszwecken optional sind.
Wenn Sie einen dieser Ansätze verwenden, können Sie die Fehlermeldung später bei Bedarf einfacher internationalisieren.
Ein Stack-Trace mit mindestens einem Minimum gibt Ihnen die Funktion und möglicherweise die Zeilennummer. Daher sollten Sie sich darauf konzentrieren, Informationen bereitzustellen, die daraus nicht einfach zu ermitteln sind.
quelle
Ich werde nicht von den Ratschlägen in Bezug auf Krzysztofs Blog ablenken, aber hier ist eine kinderleichte Möglichkeit, benutzerdefinierte Ausnahmen zu erstellen.
Beispiel:
<?php require_once "CustomException.php"; class SqlProxyException extends CustomException {} throw new SqlProxyException($errorMsg, mysql_errno()); ?>
Der Code dahinter (den ich irgendwo ausgeliehen habe, entschuldige mich bei wem auch immer das war)
<?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()}"; } }
quelle
Weitere Informationen zum Entwerfen von Ausnahmehierarchien finden Sie im Blog von Krzysztof Cwalina, einem Mitautor der "Framework Design Guidelines".
quelle
Vertrauen Sie niemals einem Benutzer, dass er das Richtige tut, und geben Sie Informationen zum Debuggen an. Wenn Sie Informationen wünschen, müssen Sie diese selbst sammeln und an einem Ort speichern, an dem sie zugänglich sind.
Wie bereits erwähnt, werden die Benutzer es vermeiden, wenn es schwierig ist, etwas zu tun. Verlassen Sie sich also auch hier nicht auf ihren guten Willen und ihr Wissen darüber, was sie senden müssen.
Dieses Denken impliziert eine Methode, mit der Sie die Informationen sammeln und protokollieren, was impliziert, dass var_dump () irgendwo verwendet wird.
Wie von Mark Harrison gesagt, ist eine Schaltfläche, die es einfach macht, irgendwo eine Fehlermeldung zu senden, für Sie und die Benutzer fantastisch. Es macht es ihnen leicht, einen Fehler zu melden. Sie (als Empfänger) erhalten viele Duplikate, aber doppelte Informationen sind besser als keine Informationen.
quelle
Egal wie viele Details Sie hinzufügen, seien Sie sicher und beides
quelle