 |
01.05.2007, 10:06
| Nach oben
#1 | | Christian Mühlroth
Registriert seit: 04.09.2005 Ort: Nürnberg
Beiträge: 561
| Designfrage zu Exceptions in PHP5
Tag,
ich habe mal eine generell Frage zu Exceptions in PHP5. Ich habe ja jederzeit die Möglichkeit, selbstdefinierte Exceptions zu erstellen (ClassDoesNotExistException, etc..).
Da ich gerade am Aufbau meines Frameowrks bin brauche ich natürlich auch einige Exceptions.
Derzeit habe ich bereits einige Exceptions wie NotSupportedException, ClassDoesNotExistException, UnableToEstablishConnectionException usw. implementiert, jedoch sieht es in den Exceptions immer gleich aus: PHP-Code: <?php /** * The "ClassDoesNotExistException" will be thrown when a class is requested, * but the class is not registered (yet). * * @author Christian Mühlroth * @version 1.0 */ class ClassDoesNotExistException extends ExceptionHandler { /** * The costructor of the exception (will be called automatically) * * @access public * @param string $sMessage * @param integer $iCode * @return void */ public function __construct($sMessage, $iCode = 0) { // At first make sure the core exception is initialized properly parent::__construct($sMessage, $iCode); }
/** * Renders the exception-view * * @access public * @return void */ public function render() { parent::render(); }
/** * Renders the exception-view, but only a little notice * * @access public * @return void */ public function renderNotice() { parent::renderNotice(); } } ?> Bei mir übernimmt die Klasse ExceptionHandler quasi die ganze Arbeit, von daher sind die abgeleiteten Exceptions eigentlich sinnlos und nur nötiger Balast - ich persönlich find das aber besser eine ClassDoesNotExistException als eine normale Exception zu werfen.
Nun hab ich mehrere Fragen:
1.) Ab wann ist es sinnvoll, abgeleitete Exceptions zu erstellen? Ist es in meinem Fall auch sinnvoll, oder sind diese schon zu speziell? (QueryFailureException, NoConnectionEstablishedException, FileIsCorruptedException, NoTemplateWasLoadedYetException ..) Soll ich besser ModelException, ViewException etc verwenden?
2.) Wenn ich viele Exceptions habe (derzeit sind es 10 verschiedene), ab wann wird es lästig für den Server?
Oder besser: Wie vermeide ich, dass ich alle Exceptions am Anfang des Scripts in den Speicher laden muss? Ich könnte natürlich die __autoload() Funktion verwenden, aber derzeit ist diese nur für "normale" Klassen da, nicht für Exceptions. Die Exceptions befinden sich in "/exceptions/", die "normalen" Klassen dagegen in "/library/".
Wenn ich nun den Exception-Pfad in die __autoload() Fukntion mit einbezieh, dann wird ja jedesmal wenn ich eine "normale" Klasse lade, auch zu erst in dem exceptions-Ordner nachgesehn - das verbraucht mir dann auch zu viel Performance.
Gibt es dafür eine gute Lösung?
Geändert von Chr!s (01.05.2007 um 10:24 Uhr)
|
| |
01.05.2007, 17:14
| Nach oben
#2 | | Jonas
Registriert seit: 03.06.2006
Beiträge: 244
|
zu 2:
Ganz einfach. Du guckst einfach, ob der Klassenname mit "Exception" endet und lädst dann aus dem exception-Ordner, ansonsten machst du dass, was du bisher machst.
__________________ Applikations-Programmierung:
BlitzMax, BlitzPlus Webentwicklung:
PHP, (X)HTML, CSS, JavaScript, MySQL |
| |
02.05.2007, 10:19
| Nach oben
#3 | | Bastian Fenske
Registriert seit: 04.01.2006 Ort: Kassel
Beiträge: 853
|
Bei mir folgen Exceptions dem selben Namensschema, wie alle anderen Klassen und beginnen alle mit "Exception_". So findet __autoload() diese auch alle um /lib/Exception/ und es ist keine spezielle Handhabung notwendig.
Wieso implementierst du denn in den konkreten Exceptions Methoden, die nichts anderes machen, als die Methoden des Elternobjektes aufzurufen? Folgendes würde hier doch reichen: PHP-Code: <?php
class Exception_Something extends Exception_Base {} Um den Speicher brauchst du dir keinen Kopf zu machen, wenn du __autoload() verwendest. Wenn eine Exception tatsächlich geworfen wird, ist es eh Wurscht.
Und, warum leitest du Exceptions von einer Klasse ExceptionHandler ab? Entweder handelt es sich um eine Exception oder um eine Klasse, die mit Exceptions dealt.
Basti
|
| |
02.05.2007, 13:09
| Nach oben
#4 | | Christian Mühlroth
Registriert seit: 04.09.2005 Ort: Nürnberg
Beiträge: 561
| Zitat: |
Zitat von Basti Wieso implementierst du denn in den konkreten Exceptions Methoden, die nichts anderes machen, als die Methoden des Elternobjektes aufzurufen? | Das ist allerdings eine berechtigte Frage. Da hab ich wohl nich aufgepasst. Zitat: |
Zitat von Basti Um den Speicher brauchst du dir keinen Kopf zu machen, wenn du __autoload() verwendest. Wenn eine Exception tatsächlich geworfen wird, ist es eh Wurscht. | Mittels __autoload() werden auch Klassen geladen, die keine instanziierung verlangen und somit vom Repository ( = Klassenverwaltung im Framework) nicht geladen werden. Aber ich hab da schon einen Lösungsansatz, danke für den Denkanstoß. Zitat: |
Zitat von Basti Und, warum leitest du Exceptions von einer Klasse ExceptionHandler ab? Entweder handelt es sich um eine Exception oder um eine Klasse, die mit Exceptions dealt. | ExceptionHandler ist bei mir die Klasse, in der alles der Exceptions zusammeläuft - das ggf. rendering der exceptions, und das loggen. Zudem lasse ich mir so weitere Möglichkeiten offen, später noch mehr dort einzubauen.
|
| |
02.05.2007, 14:06
| Nach oben
#5 | | Bastian Fenske
Registriert seit: 04.01.2006 Ort: Kassel
Beiträge: 853
| Zitat:
Zitat von Chr!s Zitat: |
Zitat von Basti Um den Speicher brauchst du dir keinen Kopf zu machen, wenn du __autoload() verwendest. Wenn eine Exception tatsächlich geworfen wird, ist es eh Wurscht. | Mittels __autoload() werden auch Klassen geladen, die keine instanziierung verlangen und somit vom Repository ( = Klassenverwaltung im Framework) nicht geladen werden. | Verstehe ich nicht. __autoload() hat ja nichts weiter zu tun, als die entsprechende Datei mit der Klassendefinition einzubinden. Die Instanzierung bzw. der Zugriff auf statische Klassen geschieht doch eh an anderer Stelle. Wenn du bestimmte Klassen hast, die vor der Instanzierung bzw. dem statischen Zugriff über statische Methoden mit bestimmten Inhalten "geimpft" werden müssen, dann löse das besser über ein Interface. Irgendwie so: PHP-Code: <?php
function __autoload($sClassName) { // include file ...
if (in_array('IContainsConfig', class_implements($sClassName))) $sClassName::setConfig(Config::getInstance()); } Ist aber sicher keine sehr saubere Lösung ... schwer zu testen etc. Zitat: Zitat: |
Zitat von Basti Und, warum leitest du Exceptions von einer Klasse ExceptionHandler ab? Entweder handelt es sich um eine Exception oder um eine Klasse, die mit Exceptions dealt. | ExceptionHandler ist bei mir die Klasse, in der alles der Exceptions zusammeläuft - das ggf. rendering der exceptions, und das loggen. Zudem lasse ich mir so weitere Möglichkeiten offen, später noch mehr dort einzubauen.
| Dafür gibt es die Funktion set_exception_handler(). Ich würde da tatsächlich unterscheiden, zwischen der Exception, die durch ihren Typ (Klasse) die Art der Ausnahme angibt und entsprechende Infos enthält auf der einen Seite und, auf der anderen Seite, einer Klasse, die mit einem solchen Objekt umgeht, also die Werte ausliest und entsprechend verarbeitet (Logging, Ausgabe, E-Mail-Benachrichtigung). Letztere ist wohl am geschicktesten einfach nur ein leeres "beobachtbares Subjekt", bei dem sich - je nach Modus (dev, debug, productive, wasauchimmer) - verschiedene Observer einklinken können (Logger, "E-Mail-Benachrichtiger", etc.).
Basti
PS:
Ich würde es vermeiden, Umlaute (bzw. Nicht-ASCII-Zeichen) im Quellcode zu verwenden, deinen Namen also eher als "Christian Mehhlroth" angeben. Damit vermeidest du Zeichensalat, wenn andere an deinem Code mitarbeiten, deren Editoren einen anderen Zeichensatz eingestellt haben, als der deinige.
|
| |
03.05.2007, 22:42
| Nach oben
#6 | | Christian Schuhmann
Registriert seit: 09.03.2007 Ort: Nürnberg
Beiträge: 66
| Zitat:
Zitat von Basti Dafür gibt es die Funktion set_exception_handler(). Ich würde da tatsächlich unterscheiden, zwischen der Exception, die durch ihren Typ (Klasse) die Art der Ausnahme angibt und entsprechende Infos enthält auf der einen Seite und, auf der anderen Seite, einer Klasse, die mit einem solchen Objekt umgeht, also die Werte ausliest und entsprechend verarbeitet (Logging, Ausgabe, E-Mail-Benachrichtigung). Letztere ist wohl am geschicktesten einfach nur ein leeres "beobachtbares Subjekt", bei dem sich - je nach Modus (dev, debug, productive, wasauchimmer) - verschiedene Observer einklinken können (Logger, "E-Mail-Benachrichtiger", etc.). | Ich kann mir zwar ungefähr vorstellen wie das aussehen könnte, aber wärst du so nett und gibst mir ein kleines Beispiel (Klassengerüst) ?
bobby
|
| |
04.05.2007, 00:20
| Nach oben
#7 | | Bastian Fenske
Registriert seit: 04.01.2006 Ort: Kassel
Beiträge: 853
|
Sowas in der Art eben: PHP-Code:
<pre> <?php
interface IExceptionObserver { public function notify(Exception $Exception); }
class Logger implements IExceptionObserver { protected $sPath;
public function __construct($sPath) { $this->sPath = $sPath; }
public function log($sMessage) { echo "Not implemented yet: Logger::log()\n"; echo "Logfile: $this->sPath\n"; echo "Message: $sMessage\n\n"; }
public function notify(Exception $Exception) { $this->log($Exception->__toString()); } }
class Observerable { private $aObservers = array();
public function registerObserver(IExceptionObserver $Observer) { $this->aObservers[] = $Observer; }
protected function notifyObservers($m) { foreach ($this->aObservers as $Observer) $Observer->notify($m); } }
class ExceptionHandler extends Observerable { public function __construct() { set_exception_handler(array($this, 'handleException')); }
public function handleException(Exception $Exception) { $this->notifyObservers($Exception); } }
class Exception_Example extends Exception { }
$ExceptionHandler = new ExceptionHandler;
$Logger = new Logger('/path/to/logfile.log'); $ExceptionHandler->registerObserver($Logger);
$Logger2 = new Logger('/another/logfile.log'); $ExceptionHandler->registerObserver($Logger2);
throw new Exception_Example('foo'); throw new Exception_Example('bar'); Allgemeiner ist es natürlich sinniger, einen ErrorHandler zu schreiben, der eben auch die Exceptions handhabt.
Basti
Geändert von Basti (04.05.2007 um 00:32 Uhr)
|
| |
05.05.2007, 12:09
| Nach oben
#8 | | Christian Mühlroth
Registriert seit: 04.09.2005 Ort: Nürnberg
Beiträge: 561
| Zitat:
Zitat von Artemis zu 2:
Ganz einfach. Du guckst einfach, ob der Klassenname mit "Exception" endet und lädst dann aus dem exception-Ordner, ansonsten machst du dass, was du bisher machst. | Im übrigen Danke dafür, damit hab ich nochmal einiges an Ladezeit gutmachen können!
Ich hab jetzt dazu eine Lösung gefunden, die zufriedenstellend ist und super funktioniert.
|
| | |
Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1) | | | | Themen-Optionen | Thema durchsuchen | | | |
Forumregeln
| Es ist dir nicht erlaubt, neue Themen zu verfassen. Es ist dir nicht erlaubt, auf Beiträge zu antworten. Es ist dir nicht erlaubt, Anhänge hochzuladen. Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten. HTML-Code ist aus. | | | Alle Zeitangaben in WEZ +1. Es ist jetzt 07:15 Uhr.
|