Exceptions und Klassen
Philipp Söhnlein
- programmiertechnik
Hi Leute,
ich bin gerade dabei einige meiner PHP Klassen so umzuschreiben, dass ich nicht immer die Ergebnisse von Methoden abfragen muss, sondern alles in einen Try Block schreiben kann.
Aus dem hier
function foo()
{
$res=bar();
if($res===false)
{
return false;
}
else
{
$res2=baz();
if($res2===false)
{
return false;
}
else
{
return $res+res2;
}
}
}
soll also das hier werden:
function foo()
{
try
{
$res=bar();
$res2=baz();
return $res+res2;
}
catch(Exception $ex)
{
throw $ex;
}
}
Ich habe aber auch schon gesehen, dass viele die standard Exception Klasse erweitern und damit eigene Exceptionclasses implementieren.
Ich bin mir nicht ganz sicher, wozu das gut sein soll und ab wann das Sinn macht. Kann mir das jemand erklären oder ein paar Vorteile davon nennen?
Ich stelle mir das komisch vor, zu meiner eigentlichen Klasse noch 20 weitere Klassen zu definieren, die eigentlich nur die Exceptionklasse abändern/erweitern.
Ciao
Phil
Hi,
Ich habe aber auch schon gesehen, dass viele die standard Exception Klasse erweitern und damit eigene Exceptionclasses implementieren.
ja, das ist üblicherweise sinnvoll.
Ich bin mir nicht ganz sicher, wozu das gut sein soll und ab wann das Sinn macht. Kann mir das jemand erklären oder ein paar Vorteile davon nennen?
Eine Exception heißt zunächst einmal: "Da ist etwas falsch gelaufen." Diese Information ist zwar grundsätzlich nützlich, aber nicht sehr. Besser ist: "Da ist _dies_ falsch gelaufen: ...", mit der jeweiligen Information, wo der Fehler liegt. Darum implementiert man eine NumberFormatException, BadArgumentException, IndexOutOfRangeException oder DeveloperOutOfCoffeeException.
Ich stelle mir das komisch vor, zu meiner eigentlichen Klasse noch 20 weitere Klassen zu definieren, die eigentlich nur die Exceptionklasse abändern/erweitern.
Nö. Komisch ist höchstens, dass die meisten dieser Exception-Klassen einfach nur einen eigenen Namen haben, ansonsten aber absolut identisch mit der Basis-Exception-Klasse sind. Aber auch daran gewöhnst Du Dich ;-)
Cheatah
Nö. Komisch ist höchstens, dass die meisten dieser Exception-Klassen einfach nur einen eigenen Namen haben, ansonsten aber absolut identisch mit der Basis-Exception-Klasse sind. Aber auch daran gewöhnst Du Dich ;-)
Ja, wahrscheinlich ist es nur Gewohnheitssache.
Aber wo ist der Unterschied ob ich ein
throw new Exception("No ale in fridge");
oder ein
throw new noAleInFridgeException();
mache?
Und was ist wenn ich mehrere Klassen habe, in der aber zwei zufällig eine outOfRangeException definieren?
echo $begrüßung;
Aber wo ist der Unterschied ob ich ein
throw new Exception("No ale in fridge");
oder ein
throw new noAleInFridgeException();
mache?
Du kannst gezielt auf einen Exception-Typ catchen. Du willst ja irgendwas sinnvolles beim Auftreten der Exception machen, und dafür brauchst du Unterscheidungsmerkmale. Wenn du einfach nur ein "Fehler aufgetreten" ausgeben willst, kannst du dir das Exceptions-Verwenden im Prinzip auch sparen.
Und was ist wenn ich mehrere Klassen habe, in der aber zwei zufällig eine outOfRangeException definieren?
Meinst du werfen statt definieren? Wenn du nicht mehr weißt, wer die Exception geworfen hat, dann hast du zu wenige Fangstellen eingebaut. Außerdem ist in einer Exception immer ein Backtrace vorhanden.
echo "$verabschiedung $name";
Tach, Post,
Und was ist wenn ich mehrere Klassen habe, in der aber zwei zufällig eine outOfRangeException definieren?
Meinst du werfen statt definieren?
Nein, angenommen ich arbeite mit der Klasse "Downloads" und dann noch mit der Klasse "Gallery". Beide stehen in getrennten Dateien. In beiden Dateien stehen aber jeweils zufällig die Klassen outOfRangeException, dann wird PHP meckern, weil die Klasse schon definiert ist.
Sowas lösst man dann üblicherweise wohl im Vornherein mittels einem Präfix, oder?
Ciao
Phil
Hi,
Nein, angenommen ich arbeite mit der Klasse "Downloads" und dann noch mit der Klasse "Gallery". Beide stehen in getrennten Dateien. In beiden Dateien stehen aber jeweils zufällig die Klassen outOfRangeException,
die können nicht zufällig dort stehen, sondern bewusst an einer Stelle, die *die* outOfRangeException (bzw. OutOfRangeException[1]) definiert. Sie ist ja schließlich nicht Teil der Klasse, sondern des Gesamtcodes.
Sowas lösst man dann üblicherweise wohl im Vornherein mittels einem Präfix, oder?
Nein, mittels require_once.
Cheatah
[1] Ja, ich weiß, PHP ist case-insensitive. Konzeptfehler sind aber IMHO kein Grund für schlechten Code.
Nabend,
Nein, angenommen ich arbeite mit der Klasse "Downloads" und dann noch mit der Klasse "Gallery". Beide stehen in getrennten Dateien. In beiden Dateien stehen aber jeweils zufällig die Klassen outOfRangeException,
die können nicht zufällig dort stehen, sondern bewusst an einer Stelle, die *die* outOfRangeException (bzw. OutOfRangeException[1]) definiert. Sie ist ja schließlich nicht Teil der Klasse, sondern des Gesamtcodes.
Ah, das heißt ich habe nicht 2 Dateien die jeweils Klasse + Exception Klassen definieren, sondern drei Dateien: Klasse 1 + Klasse 2 + Exception Klassen. Richtig?
Das heißt, eigentlich müsste die Datei mit den Exception Klassen für jedes Projekt neu zusammengestellt werden, weil einmal brauche ich nur Klasse 1, beim nächsten Klasse 3 + 4 und bei nächsten Klasse 1 + 2 + 3 + 4. Kommt mir auch nicht so ganz richtig vor, oder doch?
[1] Ja, ich weiß, PHP ist case-insensitive. Konzeptfehler sind aber IMHO kein Grund für schlechten Code.
Da stimme ich dir zu. Nur, wie kommst du darauf?
Gruß
Phil
echo $begrüßung;
Ah, das heißt ich habe nicht 2 Dateien die jeweils Klasse + Exception Klassen definieren, sondern drei Dateien: Klasse 1 + Klasse 2 + Exception Klassen. Richtig?
Du solltest dir mal die Organisation von bereits vorhandenen Frameworks bzw. Klassensammlungen ansehen. Die beiden, die ich näher kenne sind PEAR und das Zend Framework. Während PEAR etwas lockerer mit dem Benennen der Klassen und Dateien verfährt, ist das Zend Framework recht streng. (Außerdem trägt PEAR noch Altlasten aus PHP4-Zeiten mit sich rum, ZF hingegen ist komplett auf PHP5 zugeschnitten.)
echo "$verabschiedung $name";
Nabend,
Ah, das heißt ich habe nicht 2 Dateien die jeweils Klasse + Exception Klassen definieren, sondern drei Dateien: Klasse 1 + Klasse 2 + Exception Klassen. Richtig?
Du solltest dir mal die Organisation von bereits vorhandenen Frameworks bzw. Klassensammlungen ansehen.
Wenn ich mir das ZEND Framwork ansehe, da wird das ganze mit einem Prefix gemacht. Prinzipiell wird von der Exception Klasse die Zend_Exception abgeleitet und dann je nach "Anwendungsklasse" nochmal eine extra. Also da wird dann aus Zend_Exception noch z.B. Zend_Pdf_Exception.
Nach dem Beispiel von Zend hätte ich dann quasi eine downloads_outOfRangeException (extends downloadsException) und eine gallery_outOfRangeException (extends galleryException).
Ciao
Phil
echo $begrüßung;
Nach dem Beispiel von Zend hätte ich dann quasi eine downloads_outOfRangeException (extends downloadsException) und eine gallery_outOfRangeException (extends galleryException).
Gut beobachtet. Wenn man keine Namespaces hat, muss man sich eben mit eindeutigen Namen behelfen.
echo "$verabschiedung $name";
Hallo Phil,
Ich habe aber auch schon gesehen, dass viele die standard Exception Klasse erweitern und damit eigene Exceptionclasses implementieren.
Ich bin mir nicht ganz sicher, wozu das gut sein soll und ab wann das Sinn macht. Kann mir das jemand erklären oder ein paar Vorteile davon nennen?
Werfen wie in deinem Beispiel bar() und baz() die gleiche Exception, kann im catch-Block nicht unterschieden werden, woher die Exception kommt. Wenn du später mal die Fehler von bar() und baz() unterschiedlich behandeln wölltest, könntest du höchstens nach getMessage() unterscheiden. Dazu müsstest du aber genau wissen, was von den beiden Funktionen dort reingeschrieben wird und dass es in jedem Fall unterschiedlich ist - in jedem Falle kein sauberer Ansatz.
Vorausgesetzt, du hast zwei abgeleitete Exception-Klassen BarException und BazException, könntest du dies ganz elegant so lösen:
function foo ()
{
try {
$res = bar();
$res2 = baz();
return $res + $res2;
} catch (BarException $ex) {
// Tue irgendetwas
} catch (BazException $ex) {
// Tue irgendetwas anderes
}
}
Ein weiterer Vorteil des expliziten Fangens einer abgeleiteten Exception-Klasse ist der Schutz vor unvorhergesehenem Programmverhalten. Angenommen eine von bar() aufgerufen Funktion (oder eine darin aufgerufene Funktion, etc.) wirft eine Exception die in bar() nicht abgefangen wird. Wenn du catch (Exception $e) in foo() verwendest, wird damit auch diese Exception abgefangen, ohne dass du merkst, dass überhaupt eine andere Exception geworfen wurde. Das kann u.a. die Fehlersuche erschweren oder dazu führen, dass Fehler nicht bemerkt werden.
Schöne Grüße,
Johannes