Verschachtelte Klassen + error handling
kevink
- php
Hallo,
Ich habe ca. 15 verschiedene Klassen, die alle mit einander in Beziehung stehen.
Beispiel:
Die XMLRPC Klasse, ist eine fertige Klasse um per XML RPC Methoden von anderen Server mit Parametern anzusprechen und den Rückgabewert zu erhalten.
Die Server Klasse ist nutzt die XMLRPC Klasse, um das ganze zu vereinfachen.
Die Transfer Klasse, und viele anderen Klassen, nutzen die Server Klasse, um z.b. Dateien von einem zu einem anderen Server zu übertragen.
Jedoch wird auch wiederrum die Transfer Klasse von anderen "höheren" Klassen genutzt.
Derzeit habe ich das Problem mit Fehlern, die zwischen den einzelnen Klassen passieren.
Nehmen wir an, die XMLRPC Klasse kann folgende Fehler zurückgeben:
Wir mitteile ich der Server Klasse, einen dieser Fehler?
Werfe ich eine Exception? Gebe ich nur "false" zurück? (Wobei ich wissen muss, *was* aufgetreten ist).
Oder gebe ich einen Zahlenwert von -1 bis -100 für die verschiedenen Fehler zurück?
Ansich kapiere ich das allgemein, das Rückgeben von *bekannten* Fehlern, wo *bekannte* Routinen vorhanden sind, zwischen den einzelnen Klassen noch nicht.
Wie lößt man das sauber und vorallem richtig?
Danke, ich hoffe ihr könnt mir weiterhelfen.
Gruß
Kevin
echo $begrüßung;
Wir mitteile ich der Server Klasse, einen dieser Fehler?
Wie lößt man das sauber und vorallem richtig?
An dieser Stelle gibt es weder "sauber" noch "richtig", nur verschiedene Meinungen, auch von Personen, die man als "gleichwertig" einstufen kann. Alle Seiten können nachvollziehbar ihre Gründe für oder gegen eine der Weisen darlegen, ohne dass man von neutralem Standpunkt aus eine Weise sehen kann, die entschieden mehr Vorteile bietet. Letztlich bleibt es deine Entscheidung, denn du musst damit leben.
Zunächst wäre zu definieren, was als Fehler und was als normales "zwar erfolgreich, aber kein Ergebnis" ist.
Werfe ich eine Exception? Gebe ich nur "false" zurück? (Wobei ich wissen muss, *was* aufgetreten ist).
Wenn es kein Fehler, keine Ausnahmesituation ist, sollte keine Exception herhalten. "Teilstring im String nicht gefunden" kann als false oder als -1 signalisiert werden. Das ist im Allgemeinen keine Ausnahmesituation. Es wäre dann eine, wenn an dieser Stelle aufgrund der Programmlogik ein positives Ergebnis zwingend notwendig ist. Es ist also immer eine Einzelfallentscheidung, ob eine Ausnahme oder kein Ergebnis vorliegt.
Oder gebe ich einen Zahlenwert von -1 bis -100 für die verschiedenen Fehler zurück?
Wenn der negative Zahlenwert innerhalb eines erlaubten Ergebnisses ist, dann ist das natürlich kein gehbarer Weg.
Ansich kapiere ich das allgemein, das Rückgeben von *bekannten* Fehlern, wo *bekannte* Routinen vorhanden sind, zwischen den einzelnen Klassen noch nicht.
Ein "bekannter" Fehler wäre, dass der Verbindungsaufbau zu einem externen Server fehlschlagen kann. Es wäre aber eine Ausnahmesituation, denn normalerweise wird wohl von einer erfolgreichen Verbindung ausgegangen. Sämtliche von dieser Verbindung abhängige nachfolgende Programmlogik kann nun nicht mehr ausgeführt werden. Ob diese Entscheidungen in if- oder Exception-Blöcken am besten aufgehoben sind, liegt im Auge des Betrachters.
echo "$verabschiedung $name";
Hello,
wie wäre es denn mit einer eigenen Klasse fürs Errorhandling, die dann für jede Methode der anderen Klassen die Ergebnisse (Fehlerwerte) aufnimmt und so abfragbar macht?
Das trennt dann sauber Funtkionsergebnis und Fehlerkanal.
Ein harzliches Glückauf
Tom vom Berg
http://bergpost.annerschbarrich.de
Hallo,
@dedlfix:
Danke für deine ausführliche Antwort.
In meinen Verwendungszweck gibt es ansich keine Ausnahmesituation, vor jeder Aktion prüfe nach, ob die Aktion erfolgreich wird oder nicht (ein file_exists() vor einem file read z.b.).
Zwar kann zwischen dem prüfen und dem lesen der Datei, die Datei verschwinden, jedoch müßte ich trotzdem manuell die Exception werfen (throw new Ex..), was bedeuetet, das ich *zweimal* ansich die gleiche Aktion überprüfe.
Einmal davor, und einmal die Aktion selber.
Ich habe mir bereits folgendes überlegt:
In einem rießen großen Array, steht von jeder Klasse und jeder Methode, alle Verfügbaren Fehlermeldungen:
$_errors[1] = array("ERR_DB_CONNECTION_FAILED", "db connection failed", ERR_CRITICAL);
$_errors[50] = array("ERR_EXEC_ERRORCODE_FALSE", "return code was not 0", ERR_NORMAL;
Sollte nun irgendwo in einer Methode ein Fehler auftreten, gebe ich z.b. die ID 50 zurück:
return 50;
So weiß ich nun anhand des error-arrays + rückgabewert *irgendeiner methode* genau, woher der Fehler kommt und was das genau für ein Fehler ist.
Jedoch leitet darunter stark die Modularität, ich bin immer abhängig von diesen Error-Codes, und besonders sauber scheint mir das auch nicht zu sein.
wie wäre es denn mit einer eigenen Klasse fürs Errorhandling, die dann für jede Methode der anderen Klassen die Ergebnisse (Fehlerwerte) aufnimmt und so abfragbar macht?
Das trennt dann sauber Funtkionsergebnis und Fehlerkanal.
Wie würde so eine Errorhandling Klasse aussehen?
Kann mir darunter nichts vorstellen.
Danke.
Gruß
Kevin
Ein harzliches Glückauf
Tom vom Berg
Hello,
In meinen Verwendungszweck gibt es ansich keine Ausnahmesituation, vor jeder Aktion prüfe nach, ob die Aktion erfolgreich wird oder nicht (ein file_exists() vor einem file read z.b.).
Das kannst Du gar nicht prüfen, da es eine typische "TOCTOU-Situation" ist
http://www.google.de/search?q=TOCTOU&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:de:official&client=firefox-a
Ein harzliches Glückauf
Tom vom Berg
http://bergpost.annerschbarrich.de
.
Hallo,
Danke für die vielen Antworten, ich werde mich wohl nun mit Exceptions auseinander setzen.
Habe bereits meine eigene Exception Klasse geschrieben, die nun über globale Error-Meldungen verfügt, die wiederrum in einer anderen Klasse gelagert werden.
Jedoch muss das noch ausgebaut werden :o).
Danke.
Gruß
Kevin
Hello,
In meinen Verwendungszweck gibt es ansich keine Ausnahmesituation, vor jeder Aktion prüfe nach, ob die Aktion erfolgreich wird oder nicht (ein file_exists() vor einem file read z.b.).
Das kannst Du gar nicht prüfen, da es eine typische "TOCTOU-Situation" ist
http://www.google.de/search?q=TOCTOU&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:de:official&client=firefox-aEin harzliches Glückauf
Tom vom Berg
Hello,
Danke für die vielen Antworten, ich werde mich wohl nun mit Exceptions auseinander setzen.
Habe bereits meine eigene Exception Klasse geschrieben, die nun über globale Error-Meldungen verfügt, die wiederrum in einer anderen Klasse gelagert werden.Jedoch muss das noch ausgebaut werden :o).
Halte uns hier bitte auf dem Laufenden über Deine Fortschritte.
Ich bin sicher, dass das viele Forumsbesucher interessieren sollte, sie wissen es nur selber meistens gar nicht und schalten lieber ihre Fehlermeldungen ab.
Apropos Fehlermeldungen:
Deine Fehlerklasse sollte auch für jede andere Klasse Direktiven vorschreiben, wann
Ein harzliches Glückauf
Tom vom Berg
http://bergpost.annerschbarrich.de
echo $begrüßung;
In meinen Verwendungszweck gibt es ansich keine Ausnahmesituation, vor jeder Aktion prüfe nach, ob die Aktion erfolgreich wird oder nicht (ein file_exists() vor einem file read z.b.).
Dein Programm ist Hellseher?
Zwar kann zwischen dem prüfen und dem lesen der Datei, die Datei verschwinden, jedoch müßte ich trotzdem manuell die Exception werfen (throw new Ex..), was bedeuetet, das ich *zweimal* ansich die gleiche Aktion überprüfe.
Einmal davor, und einmal die Aktion selber.
Du wirst nicht drumrum kommen, den Erfolg deiner Aktion zu prüfen. Du kannst beispielsweise nicht testen, ob ein DBMS eine Verbindung mit dir akzeptiert, wenn du diese Verbindung nicht aufbaust. Die Prüfung, ob das DBMS zur Verfügung steht ist nun bereits ein Hinterher. Wenn das DBMS beim Abfragen die Grätsche macht, dann ist das auch wieder ein Hinterher und kein Vorabprüfen. Wenn es keine gewichtigen Gründe für eine Vorabprüfung gibt, tät ich die mir sparen, und nur eine Erfolgsprüfung vornehmen.
Ich habe mir bereits folgendes überlegt:
In einem rießen großen Array, steht von jeder Klasse und jeder Methode, alle Verfügbaren Fehlermeldungen:
Schau dir lieber an, wie andere ihre Klassensammlung organisieren. Beispielsweise das Zend Framework. Die diversen Funktionalitäten sind in Paketen und teilweise Unterpaketen gegliedert. In diesen gibt es jeweils eigene Exceptions-Klassen, die die anderen Klassen dieser Pakete werfen können. Zu jeder Methode ist dokumentiert, welche Exception geworfen wird, so dass der Aufrufer sehen kann, was eventuell auf ihn zukommt.
Sollte nun irgendwo in einer Methode ein Fehler auftreten, gebe ich z.b. die ID 50 zurück:
return 50;
Bleibt die Frage, wie der Fehlerzustand von einer erfolgreichen Unternehmung zu unterscheiden ist. Außerdem ist jeder Rückgabewert einzeln zu prüfen. In einem try-Block kann man hinterenanderweg das notieren, was normalerweise passieren soll. Und im catch-Teil sammelt man die Fehlerbehandlung.
So weiß ich nun anhand des error-arrays + rückgabewert *irgendeiner methode* genau, woher der Fehler kommt und was das genau für ein Fehler ist.
Genau dies können Exceptions leisten. Sie haben diverse Standard-Eigenschaften, wie Errorcode und Meldungstext und können um beliebige Eigenschaften erweitert werden.
Jedoch leitet darunter stark die Modularität, ich bin immer abhängig von diesen Error-Codes, und besonders sauber scheint mir das auch nicht zu sein.
Frag einfach die Exception, was sie für ein Problem zu berichten hat, dann musst du dir keine Gedanken machen, wo du zum Code die passende Meldung herbekommst.
Am besten probierst du beide Ansätze aus und lernst dabei ihre Eigenschaften kennen und kannst sie als Vor- oder Nachteil einsortieren. Das mit dem Array ist so ähnlich in PEAR implementiert. Das wurde unter PHP4 erfunden, als es noch keine Exceptions gab. Im Fehlerfall wird immer ein PEAR_Error-Objekt statt des eigentlichen Wertes zurückgegeben. Das muss man ständig prüfen, denn ein PEAR_Error-Objekt hat nicht die Eigenschaften, die man normalerweise von seinem Rückgabewert erwartet. Das Zend Framwork hingegen setzt auf PHP5 auf und kann damit alle modernen OOP-Möglichkeiten nutzen, wie eben auch Exceptions.
echo "$verabschiedung $name";
echo $begrüßung;
wie wäre es denn mit einer eigenen Klasse fürs Errorhandling, die dann für jede Methode der anderen Klassen die Ergebnisse (Fehlerwerte) aufnimmt und so abfragbar macht?
Warum sagst du nicht gleich, dass du Exceptions meinst? Bei einer Exception wird ein Objekt einer Exception-Klasse, die man um beliebige Eigenschaften und Methoden erweitern kann, erzeugt. Man kann solche Exceptions gezielt abfangen, und darauf angemessen reagieren, oder man kann sie ignorierend an den übergeordneten Aufruf durchreichen. Man kann auch eine neue Exception generieren und die alte in eine Eigenschaft einhängen. Somit geht der eigentliche Grund nicht verloren, die übergeordneten Aufrufe bekommen aber eine Exception, die sie kennen sollten, und keine von "ganz unten", die sie sowieso nicht behandeln können, weil sie gar keine Details der "Schmutzarbeit" kennen.
echo "$verabschiedung $name";