Dred: OOP php: verschachtelte Klassen und ein Zugriff auf eine Eigensc

Beitrag lesen

Hallo hallo,

zunächst möchte ich mich für mein gestriges Posting entschuldigen und Dir für Deine heutige Antwort sehr danken.

Entschuldigung auch für das falsche Zitat, war als Witz gedacht :)

Nun zu meinem Problem. Ich sortier mal die Antwort etwas um. Bitte nicht als Manipulationsversuch werten, auch wenn deine Intention eine andere war.

Letztendlich hängt hier eben alles an der Frage: Was soll deine Softwarelösung dir bringen, und wärst du bereit, deine Voreingenommenheit zugunsten deiner aktuellen Lösung zu überwinden?

JAAAAa, ich bin bereit meine Voreingenommenheit zu überwinden. Sonst wäre ich nicht bis hier gekommen (Stichwort OOP  :)

Bei den Exceptions ist es auch so, dass man erst sagt: "Kram, brauch ich nicht" und sie dann vermutl. etwas inflationär einsetzt. Vielleicht hast Du damit recht:

Vermutlich wirfst du an zuvielen Stellen Exceptions.

Ok. Was soll meine Softwarelösung bringen? Recht hast Du, dass die Klassen ja nicht unabhängig voneinander sind, wenn ich im Site-Constructor die DB-Klasse instantiiere.

Anders Beispiel:
ich habe eine Klasse gebaut, die aus einer ASCII-Datei ein Objekt erstellt. Diese Ascii-Datei ist eine Art Steuerdatei um Einstellungen (Klimamodell) über unterschiedliche Plattformen und Programmiersprachen auszutauschen. Sie ist untergliedert durch Steuerzeichen, wie "#", "##", "&", EOL,...
Es ist ein Austauschformat, was wir definiert haben.

Die Klasse liest die Datei und erstellt ein php-Objekt daraus. Ebenso ist es fähig, diese Datei wieder zu schreiben. Manipulieren einer Steuerdatei würde es treffen. DIESE Klasse soll standalone fähig sein, da die spätere Verwendung in meinem CMS nicht zwingend ist. Sie liest also die ASCII Datei und prüft auf um die 40 Konsistenzfehler (neben Datei vorhanden auch: Anzahl Blöcke wie erwartet?, Anzahl Spalten in jeder Zeile gleich?, Zelle enthält Wert/Array?). Wenn eine(!) Exception anspringt wird die Eigenschaft des Objektes mit den Daten gelöscht und die Exception landet im ExceptionHandler(). Von dort delegiere ich sie an meine Site. Ich schreibe in den ExceptionHandler() groß rein:

"Achtung: hier bitte persönliche Einstellungen vornehmen, blabla..."

Ich habe das so gemacht, wie es da stand mit GLOBAL $Site;

Der Vorteil: die Klasse kann jeder verwenden und muss nur an einer einzigen Stelle (im ExceptionHandler()) Änderungen vornehmen. Notfalls liefere ich die Klasse aus mit echo $e; im ExceptionHandler().

Das bedeutet, dass du es für möglich erachtest, dass sich beim Aufrufen deines Skriptes mehrere Exceptions nacheinander ansammeln. Ist das sinnvoll? Tritt sowas in der Realität tatsächlich auf?

Mehrere Exceptions dieser Klasse sind nicht zu erwarten. Mehrere Exceptions für einen Request aber schon, wenn andere Module/Klassen auch Exceptions an die Site delegieren.

Diese Methode funktioniert nun nicht im Falle der DB, die bereits im Constructor der Site instantiiert wird, da wie gesagt das Objekt $Site erst nach dem Konstruktor zu existieren scheint. Logisch. Nach meinem bisherigen Fahrplan komme ich also nicht weiter.

Momentan (nach dem gestrigen Posting) löse ich es nun so, dass die DB die Exception wirft und sie vom Konstruktor der Site gefangen wird.

Das verstehe ich nicht ganz:

Gibst du der Site im Konstruktor oder in einer separaten Methode ein Datenbankobjekt zur Verwendung, dann muss die Datenbankklasse nicht mehr zwingend "DB" heißen, sie muss nur noch sämtliche Methoden implementieren, die Site aufruft. Und um das sicherzustellen, wird man sehr wahrscheinlich ein Interface definieren, welche als Kontrollinstanz dafür sorgt, dass sämtliche Methoden, die zur Verfügung gestellt werden müssen, auch implementiert sind. Umgekehrt dokumentiert das Interface, welche Methoden man überhaupt benutzen darf, bzw. auf welche Methoden man sich verlassen kann.

AUS DEINEM ANDEREN POSTING:

Und zum Zweiten: Warum hast du in der Funktion überhaupt ein try/catch? Das finde ich schon falsch. Entweder Code ruft innerhalb von try diverse Funktionen auf, die IHRERSEITS eventuell Exceptions werfen und damit den Sprung in den (evtl. passenden, vgl. Exception-Typen oben) catch-Block veranlassen, oder es wird Code ausgeführt, der seinerseits Exceptions wirft - dann steckt der aber eben gerade nicht in einem try/catch.

Ich habe in public deklarierten Methoden einen eigenen try-catch-Block. Ansonsten stets darauf geachtet, dass in der aufrufenden Methode ein solcher steht.

Wenn du aber innerhalb von try eine Exception wirfst, um in den catch-Block derselben Funktion "weiter unten" zu gelangen, ist das erstmal ein Mißbrauch von Exceptions zur Programmflusssteuerung. Für sowas gibt es ehrlichere Methoden.

Also zu meiner Verteidigung: ich verwende die Exceptions nie, um in den catch Block weitere Anweisungen zu verarbeiten. Dort steht stets nur
$this->ExceptionHandler($e);. :)

Nun noch ein paar weitere Zitate..............................

Das widerspricht sich meiner Meinung nicht: Meine Aussage{

Das heisst, jede Klasse kümmert sich erstmal selbst um seine Exceptions.

} Deine Aussage {

Das ist halt schon genau das, was ich an deinem Konzept nicht mag. Eine Exception wird geworfen, weil ein nicht umgehbares Problem aufgetreten ist, und der Code an dieser Stelle nicht sinnvoll im vorgesehenen Fahrplan weitermachen kann.

Das wiederum bedeutet, dass die aufgerufene Methode eben gerade NICHT das gewünschte Ergebnis zu liefern imstande ist. Der Codeteil, der diese Methode aufrief, kann also ebenfalls nicht wie geplant weitermachen.

}

Die Gestaltung von Exception-Klassen und deren Vererbung ist ein gar nicht mal simples Thema. Im Gegensatz zu anderen Klassen müssen alle Exceptions, die man selbst gestaltet, von der in PHP integrierten Klasse "Exception" erben.

Ich habe keine Exception-Klasse definiert und möchte das auch nicht. Ich nutze von den Exceptions nur die Message und den Errorcode.

Sehr interessant. Aber leider noch zu hoch für mich...

Es gibt Leute, die hiervon ausgehend Exception-Typen basierend auf der Art des aufgetretenen Problems werfen, beispielsweise die InvalidArgumentException für fehlerhafte Parameter (als Kind der "LogicException"), und die UnexpectedValueException für das Auftreten unerwarteter Werte (als Kind der "RuntimeException"). Dieser Ansatz versucht, die auftretenden Probleme nach Typen zu gruppieren (die genannten Exceptions sind in PHP über die Standard PHP Library "SPL" verfügbar), so dass man in der Lage ist, je nach Fehlertyp die eine oder andere Fehlerbehebung zu versuchen, oder dem User eine entsprechende Fehlermeldung zu übermitteln.

Das klingt äußerst interessant. Kennst Du einen Beitrag im Internet (Tutorial, Ähnliches) wo dieses Prinzip vorgestellt wird. Ich verstehe es näcmlich leider nicht ganz:

Mein persönlicher Favorit hingegen ist, dass Exceptions nach den Klassen gruppiert vererbt werden, die thematisch als Module in einer Software auftreten: Eine Datenbankklasse "Db" wirft eine Db_Exception. Das darin enthaltene Modul Db_Connector wirft eine Db_Connector_Exception. Der Db_Connector_Mysql wirft eine Db_Connector_Mysql_Exception. Und die Exceptions erben in einer Kette jeweils voneinander. Damit wäre man in der Lage, auf einer sehr hohen Programmebene beim Aufruf der Methoden der Klasse "Db" mit try/catch alle Db_Exceptions zu fangen (man weiß dann, dass irgendwas in der Datenbankabfrage schief gelaufen ist und man kein Ergebnis bekommt), inklusive aller Db_Connector_Exception (weil z.B. der konfigurierte Datenbanktreiber nicht geladen werden konnte) und aller Db_Connector_Mysql_Exception (z.B. für fehlerhafte SQL-Querys).

Innerhalb der Db-Klasse würde man mit try/catch alle Db_Connector_Exception fangen können, in Db_Connector wären das Db_Connector_Mysql_Exception, etc... Wobei das Fangen nur Sinn ergibt, wenn man ein passendes Alternativprogramm anbieten kann.