Halihallo Christian
noch nichts von SIG__DIE__ gehört? :) Ich persönlich arbeite viel so:
Die Idee ist wirklich sehr gut, nur bei der Umsetzung in einem OOP-
Kontext habe ich einige kleine Bedenken (die Vorteile überwiegen
jedoch).
Geht eigentlich recht angenehm und braucht nicht diese ekeligen
eval-Konstrukte. Du kannst $SIG{__DIE__} sogar lokal überschreiben:
Deine Lösung umgesetzt, würde in etwa folgendes Konstrukt als Äquivalent für try-catch-finally vorsehen:
sub doSomething($) {
my ($self) = @_;
local $SIG{__DIE__} = sub { $self->classErrorHandler(@_); }
# do whatever throws probabely an exception...
}
sub classErrorHandler($$) {
my ($self,$error_message) = @_;
# do something with $error_message
}
oder aber:
sub doSomething($) {
my ($self) = @_;
local $SIG{__DIE__} = sub {
my ($err) = @_;
print($err->getErrorDesc() . ' at line: '.$err->getLine());
exit(255);
}
# do whatever throws probabely an exception... eg:
die( new Error('ERR_NO_VALID_CHARACTER', 'ä ist ungültig') );
}
Randbemerkung: Das ErrorHandling operiert nicht ausschliesslich im
package main, sondern auf Objects und Klassen. Deshalb machen
allgemeine (globale, staatische Funktionsaufrufe) Konstrukte wie $SIG
{__DIE__} = &fatal; wenig Sinn; aber das Umsetzen in OOP kannst du
ja ruhig mir überlassen :-)
Hm. Die zweite Version wirft nicht wesentlich mehr Overhead für das
ErrorHandling auf. Was mich daran etwas stört ist
a) das ErrorHandling wird *vor* dem eigentlichen Fehlerverursacher
definiert. Dies halte ich für Verwirrend und unschön. Der
Programmfluss wird "verschleiert" und verschlechtert die
Lesbarkeit des Codes.
b) Signale dieser Art haben in OOP absolut nichts zu suchen; jedoch
ist dein Vorschlag einem eval-Konstrukt dennoch vorzuziehen.
c) in der ersten Version braucht man eine separate Klassenmethode
für das ErrorHandling, aber verschiedene Methoden brauchen u.U.
auch verschiedene Verarbeitungsvorschriften für die Exceptions.
Natürlich könnte man jeweils den Methodennamen als Parameter
übergeben, oder caller() auswerten, jedoch ist dies viel zu viel
Overhead.
Oder man schreibt für jede Methode eine eigene ErrorHandler-
Methode, was jedoch viel zu viel Overhead bedeutet.
=> die erste Version ist untragbar.
Was ich an dieser Lösung sehr schön finde ist:
a) Es ist ziemlich einfach und universell.
b) Es generiert nicht allzuviel Overhead (Tipparbeit)
c) der Signalhandler wird trotz umschreiben des Signals automatisch
wiederhergestellt, der Programmfluss ist also "stabil". Thanks
to local. Alles andere wäre böse[tm].
d) kein böses eval
e) Das local $SIG{__DIE__} Verfahren ist selbst bei verschachtelten
Aufrufen noch korrekt, da der Kontext der Fehlerbehandlung im
Methoden-Scope stattfindet. Alles andere wäre böse[tm].
Ich hoffe, das hilft. Vorsicht aber: auch in eval()-Blöcken wird
der Callback von die() ausgeführt! Als ggf. überschreiben per local.
Wieso? - Ich zähle sogar darauf, dass er ausgeführt wird, ansonsten
sehe ich die Fehlermeldung nicht...
-------------
Vielen Dank Christian, das war wirklich ein sehr interessanter und
guter Vorschlag! - Obgleich unschön... Aber das hängt nicht an uns,
sondern an Perl, leider...
Viele Grüsse
Philipp