Der-Dennis: OOP / MVC / Routing in Bootstrap-Prozess oder Front-Controller?

Hallo zusammen,

ich arbeite gerade an einem kleinen PHP-Framework. In erster Linie, weil ich die ganzen Prozesse besser verstehen will und zweitens, weil mir andere Frameworks - wie soll ich sagen - zu "überladen" sind.

Ich hatte auch schon ein kleines Framework, habe es aber vor ein paar Tagen eingemottet, da ich hierbei nicht konsequent sauber programmiert habe, was ja bekanntlich ab einem bestimmten Punkt Erweiterungen sehr erschwert.

Nun zu meiner Frage: Gehört das Routing in den Bootstrap-Prozess oder ist es die Aufgabe des Front-Controllers, dies zu übernehmen?

Bisher rief mein Front-Controller eine Routing-Klasse auf, in der wiederum verschiedene Router (und diese konnten wiederum verschiedene Routen beinhalten) ausgeführt wurden.

Allerdings erscheint mir das nicht mehr ganz so stimmig: Der Front-Controller sollte doch eigentlich nur ein "vollständiges", also bereits geroutetes (gibt's dieses Wort eigentlich?) Request-Objekt bekommen und eine Antwort zurückgeben?

Aber wohin dann mit dem Routing? In den Bootstrap-Prozess? Auch das ist für mich nicht ganz stimmig. Denn bislang war meine grobe Struktur:

  • Anwendung wird aufgerufen: Alle für die Anwendung unabdingbaren "Prozesse" werden initialisiert und gestartet
  • Bootstrapping: Alle optionalen Plugins, Aufgaben, etc. werden geladen und evtl. ausgeführt
  • Der Front-Controller übernimmt, delegiert also an spezielle Controller und gibt am Ende die Response aus

An diesem Punkt komme ich zur Zeit nicht weiter und freue mich auf Eure Erfahrungen und Meinungen.

Gruß, Dennis

Btw: Hat jemand Interesse, mit mir zusammen ein kleines, sagen wir, Self-Framework in PHP (wenn's sein muss auch Perl :-)) zu entwickeln? Vielleicht könnte man es auch gleich so dokumentieren, dass es so verständlich wie möglich ist und man es direkt - mit weiteren Erläuterungen - für einen "MVC-Crashkurs" ins Wiki übernehmen könnte?

  1. Hi!

    ich arbeite gerade an einem kleinen PHP-Framework. In erster Linie, weil ich die ganzen Prozesse besser verstehen will und zweitens, weil mir andere Frameworks - wie soll ich sagen - zu "überladen" sind.

    Die Frage ist, welcher Funktionsumfang soll's denn sein? Je mehr Wünsche implementiert werden, desto überladener wirkt es. Du fängst mit deinem zwar klein an, aber letztlich sieht es in gewissem Rahmen auch überladen aus, wenn du Funktionalität reinbringst, die du nur für bestimmte Projekte benötigst, für das gerade betrachtete aber nicht.

    Ich hatte auch schon ein kleines Framework, habe es aber vor ein paar Tagen eingemottet, da ich hierbei nicht konsequent sauber programmiert habe, was ja bekanntlich ab einem bestimmten Punkt Erweiterungen sehr erschwert.

    Und dann ist die Frage, ist der Aufwand des Selbsterstellens inklusive der unvermeidlichen Tour durch den Sackgassen enthaltenden Irrgarten immer noch deutlich kleiner, als die Einarbeitung in ein bestehendes Framework? Oder spielen andere Aspekte, wie eigene Weiterbildung und dem Lernen aus Fehlern oder schlicht der Spaß an der Freude eine Rolle?

    Nun zu meiner Frage: Gehört das Routing in den Bootstrap-Prozess oder ist es die Aufgabe des Front-Controllers, dies zu übernehmen?

    Letzteres. (siehe auch weiter unten)

    Der Front-Controller sollte doch eigentlich nur ein "vollständiges", also bereits geroutetes (gibt's dieses Wort eigentlich?) Request-Objekt bekommen und eine Antwort zurückgeben?

    Wenn du schon fertig bist mit dem Routen, dann kennst du ja schon den aufzurufenden Action-Controller und hast keine Aufgabe mehr für einen Front-Controller.

    Aber wohin dann mit dem Routing? In den Bootstrap-Prozess? Auch das ist für mich nicht ganz stimmig. Denn bislang war meine grobe Struktur:

    Die Einteilung nach den Pattern ist nicht unbedingt eins zu eins auf Klassen zu übertragen. Es kann durchaus auch sein, dass in (d)einer Implementierung Pattern-Elemente und Klassen nicht aufeinanderfallen - nicht in dem Sinne, dass für ein Element mehrere Klassen benötigt werden sondern, dass Teile der Klassen X und Y für das Patternelement verwendet wurden und die anderen für andere Elemente. Ob das sinnvoll ist? Vermutlich nicht, denn man hat ja nicht umsonst diese Elemente und deren abgegrenzten Aufgabenbereich beschrieben. Also sollten auch deren Grenzen an den Grenzen der Programmierelemente (z.B. Klassen, Namespaces etc.) zu sehen sein.

    • Anwendung wird aufgerufen: Alle für die Anwendung unabdingbaren "Prozesse" werden initialisiert und gestartet

    Das ist das Bootstrapping - Urladen. Da sehe ich eigentlich nur ganz grundlegende Initialisierungsaufgaben. Der Rest ist dann eher schon Front-Controller.

    • Bootstrapping: Alle optionalen Plugins, Aufgaben, etc. werden geladen und evtl. ausgeführt

    Ob das noch Bootstrapping ist?

    • Der Front-Controller übernimmt, delegiert also an spezielle Controller und gibt am Ende die Response aus

    Der nimmt den Request entgegen (oder holt ihn sich) und routet ihn zum Ziel. Außerdem kommen weitere globale Aufgaben auf ihn zu, wie Initialisierungen für eine Lokalisierung oder das Resultat des Action-Controllers an das Ausgabemedium zu leiten.

    Lo!

    1. Hey dedlfix,

      wieder einmal vielen Dank für Deine Antwort. Du entwickelst Dich ja schon fast zu meinem persönlichen "Mentor" :-)

      Kurz mal OT: Nicht nur Du, dedlfix, hilfst mir riesig, sondern auch alle anderen, die hier ständig "rumschwirren". All die Namen aufzuzählen würde wohl den Rahmen sprengen, deshalb "DANKE!" an alle die sich hier zurecht angesprochen fühlen.
      Ich bin ja hier im Forum noch nicht allzu lange aktiv, obwohl ich den Großteil meiner Kenntnisse über HTML, CSS und JavaScript bei SelfHTML erworben habe. Nur ist die Dokumentation und das Forenarchiv einfach zu gut: Ich hatte keinen Grund, mich anzumelden oder etwas zu schreiben, da eigentlich jede Frage schon einmal behandelt wurde.

      So, jetzt aber genug und wieder zum Thema :-)

      ich arbeite gerade an einem kleinen PHP-Framework. In erster Linie, weil ich die ganzen Prozesse besser verstehen will und zweitens, weil mir andere Frameworks - wie soll ich sagen - zu "überladen" sind.

      Die Frage ist, welcher Funktionsumfang soll's denn sein? Je mehr Wünsche implementiert werden, desto überladener wirkt es. Du fängst mit deinem zwar klein an, aber letztlich sieht es in gewissem Rahmen auch überladen aus, wenn du Funktionalität reinbringst, die du nur für bestimmte Projekte benötigst, für das gerade betrachtete aber nicht.

      Hmm... Damit wirst Du wohl rechthaben. Ich wollte mich eigentlich nur auf das ganz Essentielle beschränken, was man für eine Web-Anwendung benötigt. Allerdings mit der Möglichkeit zur Erweiterung. Und wenn ich das weiterspinne, komme ich wahrscheinlich wieder zum zuvor von Dir genannten.

      Ich hatte auch schon ein kleines Framework, habe es aber vor ein paar Tagen eingemottet, da ich hierbei nicht konsequent sauber programmiert habe, was ja bekanntlich ab einem bestimmten Punkt Erweiterungen sehr erschwert.

      Und dann ist die Frage, ist der Aufwand des Selbsterstellens inklusive der unvermeidlichen Tour durch den Sackgassen enthaltenden Irrgarten immer noch deutlich kleiner, als die Einarbeitung in ein bestehendes Framework?

      Das sicherlich nicht! "Selbstgemacht" ist wesentlich aufwendiger als die Einarbeitung in Bestehendes.
      Ich nutze, vor allem in dem Institut, in dem ich arbeite, das Zend-Framework. Die Einarbeitung habe ich somit einigermaßen hinter mir. Allerdings war auch genau das der Punkt, warum ich ein eigenes, neues Framework auf die Beine stellen möchte (zusätlich zu dem Punkt nach dem nächsten Zitat): Einiges im Zend-Framework (von dem ich aber - das muss man sagen - viel gelernt und mir vieles abgeschaut habe) ist für mich nicht ganz durchschaubar und nachvollziehbar. Vieles erscheint, dass die Entwickler zeigen wollen, wie "geil" sie doch sind (und das fängt schon bei Kleinigkeiten wie array_push($array, $value) statt $array[] = $value an; auch etwas, dass ich dort gelernt habe und worüber wir uns in einem anderen Thread schon unterhalten haben).
      Oder sie treiben OOP "auf die Spitze", in dem der Name einer Datenbank-Tabelle eine eigene Klasse erhält (also nicht gezwungenermaßen, sondern bei dem, was möglich wäre). Da kann ich auch die "bei-OOP-zuviel-Overhead"-Nörgler verstehen, da für mich nach Kosten-Nutzen-Rechnung mein Argument mit der besseren Wartbarkeit - trotz Caching - verschwindend gering ausfällt.

      Oder spielen andere Aspekte, wie eigene Weiterbildung und dem Lernen aus Fehlern oder schlicht der Spaß an der Freude eine Rolle?

      Definitiv beides. Wie bereits gesagt möchte ich das ganze auch verstehen, was ich da mache. Und Spaß habe ich auch daran.

      Nun zu meiner Frage: Gehört das Routing in den Bootstrap-Prozess oder ist es die Aufgabe des Front-Controllers, dies zu übernehmen?

      Letzteres. (siehe auch weiter unten)

      Der Front-Controller sollte doch eigentlich nur ein "vollständiges", also bereits geroutetes (gibt's dieses Wort eigentlich?) Request-Objekt bekommen und eine Antwort zurückgeben?

      Wenn du schon fertig bist mit dem Routen, dann kennst du ja schon den aufzurufenden Action-Controller und hast keine Aufgabe mehr für einen Front-Controller.

      So war es bei mir bis jetzt ja auch. Also, dass der Front-Controller das Routing übernahm.
      Aber eine Aufgabe hätte der Front-Controller noch immer: Er ist die oberste Controller-Instanz. Nachdem er einen speziellen Controller aufgerufen hat, könnte dieser Controller ja noch einen anderen, speziellen Controller für eine Aufgabe benötigen. Der sollte allerdings nicht direkt, sondern über den Front-Controller aufgerufen werden, damit dieser die Entscheidung treffen kann, ob dies überhaupt möglich ist. Außerdem hatte mein Front-Controller die Aufgabe, die Response zu senden (also Header und anschließend die View).

      Aber wohin dann mit dem Routing? In den Bootstrap-Prozess? Auch das ist für mich nicht ganz stimmig. Denn bislang war meine grobe Struktur:

      Die Einteilung nach den Pattern ist nicht unbedingt eins zu eins auf Klassen zu übertragen. Es kann durchaus auch sein, dass in (d)einer Implementierung Pattern-Elemente und Klassen nicht aufeinanderfallen - nicht in dem Sinne, dass für ein Element mehrere Klassen benötigt werden sondern, dass Teile der Klassen X und Y für das Patternelement verwendet wurden und die anderen für andere Elemente. Ob das sinnvoll ist? Vermutlich nicht, denn man hat ja nicht umsonst diese Elemente und deren abgegrenzten Aufgabenbereich beschrieben. Also sollten auch deren Grenzen an den Grenzen der Programmierelemente (z.B. Klassen, Namespaces etc.) zu sehen sein.

      Das musste ich mir jetzt mehrfach durchlesen, um es zu verstehen. Aber mein Problem ist ja gerade, wo ich die Grenzen ansetzen sollte / muss.

      • Anwendung wird aufgerufen: Alle für die Anwendung unabdingbaren "Prozesse" werden initialisiert und gestartet

      Das ist das Bootstrapping - Urladen. Da sehe ich eigentlich nur ganz grundlegende Initialisierungsaufgaben. Der Rest ist dann eher schon Front-Controller.

      Auch hier liegt mein Problem. Nach meinem jetzigen System hätte ich keine Verwendung für das Bootstrapping:
      Das Laden von Konfigurationsdaten und die Initialisierung des Autoloaders finden bei mir beim Aufruf der Anwendung statt.
      Beispielsweise die Datenbankverbindung wird bei mir - weil nicht immer zwingend erforderlich - über ein Plugin im Bootstrap-Prozess initialisiert.

      • Bootstrapping: Alle optionalen Plugins, Aufgaben, etc. werden geladen und evtl. ausgeführt

      Ob das noch Bootstrapping ist?

      Das ist die Frage...?! ;-)

      • Der Front-Controller übernimmt, delegiert also an spezielle Controller und gibt am Ende die Response aus

      Der nimmt den Request entgegen (oder holt ihn sich) und routet ihn zum Ziel. Außerdem kommen weitere globale Aufgaben auf ihn zu, wie Initialisierungen für eine Lokalisierung oder das Resultat des Action-Controllers an das Ausgabemedium zu leiten.

      Wenn dem so ist, hast Du zumindest meine spezielle Frage komplett beantwortet. Wenn der Front-Controller all diese Aufgaben, die ich (weil's sich so schön anhört :-)) Plugins nenne, ausführen soll(te), haben die bei mir im Bootstrapping nichts zu suchen. Ebensowenig wie das Routing.

      Gruß und nochmal danke, Dennis

      1. Hi!

        Oder sie treiben OOP "auf die Spitze", in dem der Name einer Datenbank-Tabelle eine eigene Klasse erhält (also nicht gezwungenermaßen, sondern bei dem, was möglich wäre). Da kann ich auch die "bei-OOP-zuviel-Overhead"-Nörgler verstehen, da für mich nach Kosten-Nutzen-Rechnung mein Argument mit der besseren Wartbarkeit - trotz Caching - verschwindend gering ausfällt.

        Ich nehme an, das wird nicht nur Selbstzweck sondern für bestimmte Anwendungsfälle notwendig sein. Du bekommst diese Funktionalität ohne OOP sicher auch nicht ohne vergleichbaren Overhead hin.

        Wenn du schon fertig bist mit dem Routen, dann kennst du ja schon den aufzurufenden Action-Controller und hast keine Aufgabe mehr für einen Front-Controller.

        So war es bei mir bis jetzt ja auch. Also, dass der Front-Controller das Routing übernahm.
        Aber eine Aufgabe hätte der Front-Controller noch immer: Er ist die oberste Controller-Instanz. Nachdem er einen speziellen Controller aufgerufen hat, könnte dieser Controller ja noch einen anderen, speziellen Controller für eine Aufgabe benötigen. Der sollte allerdings nicht direkt, sondern über den Front-Controller aufgerufen werden, damit dieser die Entscheidung treffen kann, ob dies überhaupt möglich ist. Außerdem hatte mein Front-Controller die Aufgabe, die Response zu senden (also Header und anschließend die View).

        Ja, der FC hat nicht nur die Aufgabe des Routings (wie ich ja dann später auch noch sagte), insofern war mein Satz so nicht ganz richtig. Die Hauptaufgabe ist jedoch das Auswerten und Routen des Requests. Inwieweit für den Request mehrere Teilschritte zu erledigen sind, und wer die erledigt, steht auf einem anderen Blatt. Es können durchaus pro Request mehrere Actions von einem oder mehreren Action-Controllern notwendig sein. Wenn deine fertigen Seiten modular aufgebaut sind, könnte eine Action den Hauptinhalt generieren, eine andere kümmert sich um das Werbungs-Modul, und weitere Actions werden für die anderen Module aufgerufen.

        Die Einteilung nach den Pattern ist nicht unbedingt eins zu eins auf Klassen zu übertragen. Es kann durchaus auch sein, dass in (d)einer Implementierung Pattern-Elemente und Klassen nicht aufeinanderfallen - nicht in dem Sinne, dass für ein Element mehrere Klassen benötigt werden sondern, dass Teile der Klassen X und Y für das Patternelement verwendet wurden und die anderen für andere Elemente. Ob das sinnvoll ist? Vermutlich nicht, denn man hat ja nicht umsonst diese Elemente und deren abgegrenzten Aufgabenbereich beschrieben. Also sollten auch deren Grenzen an den Grenzen der Programmierelemente (z.B. Klassen, Namespaces etc.) zu sehen sein.
        Das musste ich mir jetzt mehrfach durchlesen, um es zu verstehen. Aber mein Problem ist ja gerade, wo ich die Grenzen ansetzen sollte / muss.

        Dazu sollte man generell den Sinn von Pattern und die Historie ihrer Entstehung betrachten. Sie wurden ja nicht einfach am Reißbrett entworfen, sondern jemand hat festgestellt, dass er es sich bewehrt hat, bestimmte Aufgaben immer nach dem selben Muster zu lösen. Diese Muster musste man nur erkennen, sie beschreiben und ihnen Namen geben. Man hat also eine Lösung oder Teile davon beschrieben, und aus der Beschreibung kann man nun wieder eine Implementation für ein anderes System erstellen. Sie werden idealerweise auf dem ursprünglichen System klar und deutlich zu sehen sein und auf den anderen ebenfalls. Aber allein durch die Verwendung eines Patterns ist man nicht verpflichtet, es buchstabengetreu nachzubilden. Man tut jedoch gut daran, es bei starken Abweichungen zur Beschreibung anders zu benennen, sonst ist ein außenstehender Betrachter vermutlich erstmal irritiert. Um dein Abgrenzungsproblem zu lösen, kannst du jedoch dahergehen und dir aus den formalen Beschreibungen der Patterns herauslesen, welche Aufgaben sie usprünglich zu lösen hatten und deine Implementation ebenfalls an diesen Beschreibungen auszurichten.

        • Anwendung wird aufgerufen: Alle für die Anwendung unabdingbaren "Prozesse" werden initialisiert und gestartet
          Das ist das Bootstrapping - Urladen. Da sehe ich eigentlich nur ganz grundlegende Initialisierungsaufgaben. Der Rest ist dann eher schon Front-Controller.
          Auch hier liegt mein Problem. Nach meinem jetzigen System hätte ich keine Verwendung für das Bootstrapping:
          Das Laden von Konfigurationsdaten und die Initialisierung des Autoloaders finden bei mir beim Aufruf der Anwendung statt.

        Du meinst __autoload(), um die Klassen zu laden? Nun, das könnte man ja als Teil des Bootstraps ansehen, denn schon der FC könnte ja in den Genuss kommen, damit geladen zu werden. Und schon hast du einen Bedarf für ein BS. Wie sieht es mit der Angabe, wo die grundlegende Konfigurationsdatei der Anwendung zu finden sind, aus? Die Initialisierung des Fehlerloggings könnte ebenfalls Aufgabe des BS sein. Also alle Aufgaben, die unabhängig vom und vor dem Auswerten des Request gelöst werden sollen.

        Beispielsweise die Datenbankverbindung wird bei mir - weil nicht immer zwingend erforderlich - über ein Plugin im Bootstrap-Prozess initialisiert.

        Warum kann das nicht das Model in Auftrag geben, wenn es eine benötigt?

        • Bootstrapping: Alle optionalen Plugins, Aufgaben, etc. werden geladen und evtl. ausgeführt
          Ob das noch Bootstrapping ist?
          Das ist die Frage...?! ;-)

        Kommt drauf an, was konkret da zu tun ist. Dinge rund um den Request erledigt der FC, Anwendungsinitialisierung macht das BS.

        Lo!

        1. Hey dedlfix,

          Oder sie treiben OOP "auf die Spitze", in dem der Name einer Datenbank-Tabelle eine eigene Klasse erhält (also nicht gezwungenermaßen, sondern bei dem, was möglich wäre). Da kann ich auch die "bei-OOP-zuviel-Overhead"-Nörgler verstehen, da für mich nach Kosten-Nutzen-Rechnung mein Argument mit der besseren Wartbarkeit - trotz Caching - verschwindend gering ausfällt.

          Ich nehme an, das wird nicht nur Selbstzweck sondern für bestimmte Anwendungsfälle notwendig sein. Du bekommst diese Funktionalität ohne OOP sicher auch nicht ohne vergleichbaren Overhead hin.

          dies wird sicher auch ohne OOP der Fall sein, da hab ich mich nicht richtig ausgedrückt. Nur frage ich mich, wo soll dieser Anwendungsfall sein? Mir fällt schlicht und einfach keiner ein, außer dass ich einer Datenbank-Tabelle hin und wieder einen neuen Namen geben möchte und dies dann in nur einer einzigen Datei machen müsste. Aber warum sollte ich das tun? Ich hab eine Tabelle ja nicht zum Spaß "user" genannt!?

          Ja, der FC hat nicht nur die Aufgabe des Routings (wie ich ja dann später auch noch sagte), insofern war mein Satz so nicht ganz richtig. Die Hauptaufgabe ist jedoch das Auswerten und Routen des Requests. Inwieweit für den Request mehrere Teilschritte zu erledigen sind, und wer die erledigt, steht auf einem anderen Blatt. Es können durchaus pro Request mehrere Actions von einem oder mehreren Action-Controllern notwendig sein. Wenn deine fertigen Seiten modular aufgebaut sind, könnte eine Action den Hauptinhalt generieren, eine andere kümmert sich um das Werbungs-Modul, und weitere Actions werden für die anderen Module aufgerufen.

          Danke, dann habe ich zumindest den richtigen Grundgedanken gehabt. Und meine eigentliche Frage "Routing in Bootstrap oder Front-Controller" hast Du damit vollständig beantwortet :-)

          Die Einteilung nach den Pattern ist nicht unbedingt eins zu eins auf Klassen zu übertragen. Es kann durchaus auch sein, dass in (d)einer Implementierung Pattern-Elemente und Klassen nicht aufeinanderfallen - nicht in dem Sinne, dass für ein Element mehrere Klassen benötigt werden sondern, dass Teile der Klassen X und Y für das Patternelement verwendet wurden und die anderen für andere Elemente. Ob das sinnvoll ist? Vermutlich nicht, denn man hat ja nicht umsonst diese Elemente und deren abgegrenzten Aufgabenbereich beschrieben. Also sollten auch deren Grenzen an den Grenzen der Programmierelemente (z.B. Klassen, Namespaces etc.) zu sehen sein.
          Das musste ich mir jetzt mehrfach durchlesen, um es zu verstehen. Aber mein Problem ist ja gerade, wo ich die Grenzen ansetzen sollte / muss.

          Dazu sollte man generell den Sinn von Pattern und die Historie ihrer Entstehung betrachten. Sie wurden ja nicht einfach am Reißbrett entworfen, sondern jemand hat festgestellt, dass er es sich bewehrt hat, bestimmte Aufgaben immer nach dem selben Muster zu lösen. Diese Muster musste man nur erkennen, sie beschreiben und ihnen Namen geben. Man hat also eine Lösung oder Teile davon beschrieben, und aus der Beschreibung kann man nun wieder eine Implementation für ein anderes System erstellen. Sie werden idealerweise auf dem ursprünglichen System klar und deutlich zu sehen sein und auf den anderen ebenfalls. Aber allein durch die Verwendung eines Patterns ist man nicht verpflichtet, es buchstabengetreu nachzubilden. Man tut jedoch gut daran, es bei starken Abweichungen zur Beschreibung anders zu benennen, sonst ist ein außenstehender Betrachter vermutlich erstmal irritiert. Um dein Abgrenzungsproblem zu lösen, kannst du jedoch dahergehen und dir aus den formalen Beschreibungen der Patterns herauslesen, welche Aufgaben sie usprünglich zu lösen hatten und deine Implementation ebenfalls an diesen Beschreibungen auszurichten.

          Das hört sich alles sehr schlüssig an. Heißt also für mich: Lesen! Genau lesen, was warum beschrieben wurde und wie ich es umsetzen kann.

          • Anwendung wird aufgerufen: Alle für die Anwendung unabdingbaren "Prozesse" werden initialisiert und gestartet
            Das ist das Bootstrapping - Urladen. Da sehe ich eigentlich nur ganz grundlegende Initialisierungsaufgaben. Der Rest ist dann eher schon Front-Controller.
            Auch hier liegt mein Problem. Nach meinem jetzigen System hätte ich keine Verwendung für das Bootstrapping:
            Das Laden von Konfigurationsdaten und die Initialisierung des Autoloaders finden bei mir beim Aufruf der Anwendung statt.

          Du meinst __autoload(), um die Klassen zu laden? Nun, das könnte man ja als Teil des Bootstraps ansehen, denn schon der FC könnte ja in den Genuss kommen, damit geladen zu werden. Und schon hast du einen Bedarf für ein BS. Wie sieht es mit der Angabe, wo die grundlegende Konfigurationsdatei der Anwendung zu finden sind, aus? Die Initialisierung des Fehlerloggings könnte ebenfalls Aufgabe des BS sein. Also alle Aufgaben, die unabhängig vom und vor dem Auswerten des Request gelöst werden sollen.

          Ja, ich meine __autoload()... Das wird beim starten der Anwendung geladen, damit beispielsweise der Front-Controller geladen werden kann... Also ab in den Bootstrap!
          Und die Fehlerbehandlung (gemeint ist: Weiterleitung auf einen entsprechenden Controller im Fehlerfall)... Das ist bei mir eins der zuvor beschriebenen "plugins", die beim bootstrapping geladen werden, da die Anwendung ja auch ohne Fehlerbehandlung funktionieren würde.
          Das Fehlerlogging allerdings ist bei mir wieder im Start-Teil... Ich merke, ich arbeite inkonsistent.

          Beispielsweise die Datenbankverbindung wird bei mir - weil nicht immer zwingend erforderlich - über ein Plugin im Bootstrap-Prozess initialisiert.

          Warum kann das nicht das Model in Auftrag geben, wenn es eine benötigt?

          Macht es ja indirekt. Nur werden die Datenbank-Zugangsdaten vorher ausgelesen und der DB-Klasse mitgeteilt. Erst bei der ersten Anfrage eines Models an die Datenbank wird die Datenbank-Verbindung aufgebaut.

          • Bootstrapping: Alle optionalen Plugins, Aufgaben, etc. werden geladen und evtl. ausgeführt
            Ob das noch Bootstrapping ist?
            Das ist die Frage...?! ;-)

          Kommt drauf an, was konkret da zu tun ist. Dinge rund um den Request erledigt der FC, Anwendungsinitialisierung macht das BS.

          Ich weiß nicht, ob ich zuvor genug beschrieben habe, wie es bei mir zur Zeit ist, dass man das beantworten könnte.

          Gruß und vielen Dank, Dennis

          1. Hi!

            Oder sie treiben OOP "auf die Spitze", in dem der Name einer Datenbank-Tabelle eine eigene Klasse erhält (also nicht gezwungenermaßen, sondern bei dem, was möglich wäre).
            Ich nehme an, das wird nicht nur Selbstzweck sondern für bestimmte Anwendungsfälle notwendig sein.
            Nur frage ich mich, wo soll dieser Anwendungsfall sein?

            Zeig mal genau, was du meinst. Ich finde da grad nichts, worauf deine Beschreibung konkret passt.

            Und die Fehlerbehandlung (gemeint ist: Weiterleitung auf einen entsprechenden Controller im Fehlerfall)... Das ist bei mir eins der zuvor beschriebenen "plugins", die beim bootstrapping geladen werden, da die Anwendung ja auch ohne Fehlerbehandlung funktionieren würde.
            Das Fehlerlogging allerdings ist bei mir wieder im Start-Teil... Ich merke, ich arbeite inkonsistent.

            Fehlerbehandlung ist Sache der Programmteile. Dafür kann es sinnvollerweise keinen globalen Mechanismus geben. Zu vielfältig sind mögliche Ursachen und Reaktionen.

            Ein Fehlerlogging-Mechanismus sollte unabhängig von der Anwendung arbeiten. (Natürlich kann er sich dabei der Klassen des Frameworks bedienen, wenn man annimmt, dass diese fehlerfrei laufen und nicht durch selbst erzeugte Fehler eine Endlosschleife oder anderes ungewünschtes Verhalten entsteht.) Fehler sollen ja auch schon dann protokolliert werden (können), wenn der FC nicht geladen werden kann. Denn diese Ursache will man garantiert wissen. Also sollte der Loggingmechanismus (wenn nicht schon außerhalb PHPs konfiguriert) als eine der ersten Amtshandlungen des BS initialisiert werden.

            Lo!

            1. Hey dedlfix,

              Nur frage ich mich, wo soll dieser Anwendungsfall sein?

              Zeig mal genau, was du meinst. Ich finde da grad nichts, worauf deine Beschreibung konkret passt.

              ein Beispiel aus dem Quick-Start des Zend-Frameworks:

                
              class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract  
              {  
                  protected $_name = 'guestbook';  
              }  
              
              

              Hierbei ist es so, dass die Klasse lediglich den Namen einer Datenbank-Tabelle enthält.
              Mir ist allerdings durchaus bewusst, dass die Klasse Zend_Db_Table_Abstract viele weitere Funktionalitäten beinhaltet. Aber, wo wir gerade dabei sind, mir kommt auch diese Klasse, also Zend_Db_Table_Abstract, reichlich "aufgebläht" vor.
              Wie bereits gesagt, bei den vorhandenen Frameworks haben sich viele Leute lange Zeit Gedanken drüber gemacht, aber meine derzeit (vielleicht naive) Meinung ist, dass man dies alles wesentlich "schlanker" gestalten könnte.
              Und eine abgeleitete Klasse nur wegen eines Tabellen-Namens? Für mich ist dies nach meinem OOP-Verständnis zwar folgerichtig, geht allerdings etwas zu weit.

              Außerdem, der Punkt fällt mir grad noch ein: Die aktuell mir bekannten Frameworks bieten viele, ich nenne sie mal "Komfort-Methoden", die meiner Meinung nach nicht sein müssten.
              So kann ich einen beispielsweise einen DB-SELECT direkt als SQL-Statement ausführen oder die Funktion select()->from()->was-auch-immer ausführen. Hinzu kommen viele Factory-Methoden (oder Konstruktoren), die ein Objekt, ein Array, einen String oder einen Integer entgegen nehmen können und innerhalb dieser Methode dann entscheiden, "was ich gemeint habe". Mir würde es (in den meisten Fällen) vollkommen reichen, wenn eine Methode ein Objekt eines bestimmten Typs entgegen nimmt. Dies ist ja bereits mit PHP möglich, auch wenn es noch kein vollständiges type hinting unterstützt (was ich persönlich bevorzugen würde).

              Fehlerbehandlung ist Sache der Programmteile. Dafür kann es sinnvollerweise keinen globalen Mechanismus geben. Zu vielfältig sind mögliche Ursachen und Reaktionen.

              Ok, da habe ich mich falsch ausgedrückt. Bei mir werden im Bootstrap-Prozess mittels set_error_handler() und set_exception_handler() die Klassen initialisiert, die "aufgefangene" Fehler verarbeiten und je nach Umgebung (development, testing, production) unterschiedlich handeln.
              Die eigentliche Fehlerbehandlung findet natürlich innerhalb der Anwendung statt. Ich meinte nur die Fehlerbehandlung, wenn beispielsweise eine Methode sagt: "Hier geht's für mich nicht mehr weiter". Hier könnte entschieden werden, ob eine andere Methode übernehmen könnte, ob eine Fehlerseite (abhängig von der Anwendungs-Umgebung) mit oder ohne Fehler-Details angezeigt werden soll oder das Skript mit einem fatal error o.ä. abbrechen muss.

              Ein Fehlerlogging-Mechanismus sollte unabhängig von der Anwendung arbeiten. (Natürlich kann er sich dabei der Klassen des Frameworks bedienen, wenn man annimmt, dass diese fehlerfrei laufen und nicht durch selbst erzeugte Fehler eine Endlosschleife oder anderes ungewünschtes Verhalten entsteht.) Fehler sollen ja auch schon dann protokolliert werden (können), wenn der FC nicht geladen werden kann. Denn diese Ursache will man garantiert wissen. Also sollte der Loggingmechanismus (wenn nicht schon außerhalb PHPs konfiguriert) als eine der ersten Amtshandlungen des BS initialisiert werden.

              Das mache ich erst im Bootstrapping, da mir erst hier die Konfigurationsdaten zur Verfügung stehen (in einer ini-Datei steht beispielsweise, wo sich das error-log befindet).
              Da besteht, Deinem vorherigen Absatz nach zu urteilen, allerdings Nachholbedarf. Ich sollte es wohl ganz an den Anfang der Anwendung packen.

              Wieder einmal danke und gute Nacht,
              Dennis

              1. Hello,

                ein Beispiel aus dem Quick-Start des Zend-Frameworks:

                class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
                {
                    protected $_name = 'guestbook';
                }

                  
                An dieser Stelle müsste man das Dazuladen der Konfiguration (Namensgebung) und der Zuordnungstabelle (Welche Spalte extern wird wie auf welche Spalte intern abgebildet) einbauen. Dann würde es mMn sehr sinnvoll werden.  
                  
                Ich habe gerade einen solchen Fall, wo eine Applikation geschrieben werden soll, die auf eine Datenbank zugreift. Leider ist noch nicht geklärt, ob die eine oder die andere Fremddatenbank angezapft werden soll oder nachher doch eine eigene zugrunge gelegt werden soll.  
                  
                Die Abstraktion muss also irgendwo eingebaut werden.  
                  
                Oder ist das der falsche Platz?  
                  
                  
                  
                Liebe Grüße aus dem schönen Oberharz  
                  
                  
                Tom vom Berg  
                ![](http://selfhtml.bitworks.de/Virencheck.gif)  
                  
                
                -- 
                 ☻\_  
                /▌  
                / \ Nur selber lernen macht schlau  
                <http://bergpost.annerschbarrich.de>
                
                1. Hey Tom,

                  ein Beispiel aus dem Quick-Start des Zend-Frameworks:

                  class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
                  {
                      protected $_name = 'guestbook';
                  }

                  
                  >   
                  > An dieser Stelle müsste man das Dazuladen der Konfiguration (Namensgebung) und der Zuordnungstabelle (Welche Spalte extern wird wie auf welche Spalte intern abgebildet) einbauen. Dann würde es mMn sehr sinnvoll werden. [...]  
                  > Die Abstraktion muss also irgendwo eingebaut werden. Oder ist das der falsche Platz?  
                    
                  meiner Meinung nach wäre das tatsächlich ein Anwendungsfall für so eine Klasse. Man, da habe ich über vieles einfach nicht nachgedacht :-)  
                  Nochmal zu Deiner Frage: Ich sitze grad an einem anderen Rechner, habe das Zend-Framework also nicht hier. Aber schau Dir doch mal die Klasse Zend\_Db\_Table\_Abstract an. Ich sagte ja, ich finde sie recht "überladen" :-), aber vielleicht bietet die schon so eine Funktionalität. Ich bin mir ziemlich sicher, dass sie zumindest alle Spalten einer Tabelle ausliest und intern speichert. Das wäre vielleicht ein Ansatzpunkt und dann könntest Du die Klasse mit den Zuordnungen erweitern.  
                    
                  Gruß, Dennis
                  
              2. Hi!

                class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
                Hierbei ist es so, dass die Klasse lediglich den Namen einer Datenbank-Tabelle enthält.

                Ja, das ist aber nur der einfachste Anwendungsfall. Du hast mit der Klasse nun die Möglichkeit weitere Funktionalität hinzuzufügen.

                Mir ist allerdings durchaus bewusst, dass die Klasse Zend_Db_Table_Abstract viele weitere Funktionalitäten beinhaltet. Aber, wo wir gerade dabei sind, mir kommt auch diese Klasse, also Zend_Db_Table_Abstract, reichlich "aufgebläht" vor.

                Zend_Db_Table_Abstract stellt ja seine Funktionalität mehr oder weniger auf allgemeinem Level zur Verfügung. In deiner konkreten abgeleiteten Klasse kannst du nun Methoden hinzufügen, die beispielsweise den Code für bestimmte Abfragen enthalten. Und somit hast du nicht nur Overhead sondern einen Mehrwert.

                Wie bereits gesagt, bei den vorhandenen Frameworks haben sich viele Leute lange Zeit Gedanken drüber gemacht, aber meine derzeit (vielleicht naive) Meinung ist, dass man dies alles wesentlich "schlanker" gestalten könnte.

                Ja, sicher. Man kann jedoch auch einfach die Teile ignorieren, die man nicht benötigt. Sie zu löschen ist wegen irgendwelcher Abhängigkeiten vielleicht keine gute Idee. Wenn man das aber gefahrlos hinbekäme, würde auch das Framework wieder schlanker wirken.

                Und eine abgeleitete Klasse nur wegen eines Tabellen-Namens? Für mich ist dies nach meinem OOP-Verständnis zwar folgerichtig, geht allerdings etwas zu weit.

                Das ist lediglich die Grundlage. Aber auch in dieser einfachsten Form kann das schon von Vorteil sein, denn man hat nun einen eindeutigen Klassennamen, den man für Type Hinting verwenden kann.

                Außerdem, der Punkt fällt mir grad noch ein: Die aktuell mir bekannten Frameworks bieten viele, ich nenne sie mal "Komfort-Methoden", die meiner Meinung nach nicht sein müssten.

                Kommt drauf an. Ich hab in meinem Haus einen Aufzug, den ich nicht verwende, weil ich zu Fuß meist schneller in der vierten Etage bin. Dennoch ist er beispielsweise für Lasten wie Einkäufe nützlich und ich würde ungern in ein Haus ohne Aufzug ziehen. (Schon für einen Umzug ist er eine enorme Erleichterung.)

                So kann ich einen beispielsweise einen DB-SELECT direkt als SQL-Statement ausführen oder die Funktion select()->from()->was-auch-immer ausführen.

                Dazu musst du aber den konkreten SQL-Dialekt beherrschen, wissen, wie man im Speziellen Quotierungen und Maskierungen vornimmt - im Allgemeinen also eine Menge Wissen über das DBMS mitbringen. Das ist eigentlich nicht verkehrt, aber wenn du mehr der Programmierer als der Datanbankspezialist bist, wirst du vermutlich mit den Abstrahierungen des Layers besser zurecht kommen - weil sie, wenn sie gut umgesetzt wurden, doch eher aus der Programmierersicht denn aus DB-Admin-Sicht funktionieren.

                Hinzu kommen viele Factory-Methoden (oder Konstruktoren), die ein Objekt, ein Array, einen String oder einen Integer entgegen nehmen können und innerhalb dieser Methode dann entscheiden, "was ich gemeint habe".

                Ja, das ist der PHP-Weg. Geht nicht anders bei der Art der Typisierung. In typsicheren Sprachen (wie C#) sieht der Kompiler, welche der überladenen Methoden zum übergebenen Typ passt und ruft diese gezielt auf. PHP muss/[kann erst] zur Laufzeit ermitteln, welcher Typ vorliegt und dann unterschiedlich handeln.

                Mir würde es (in den meisten Fällen) vollkommen reichen, wenn eine Methode ein Objekt eines bestimmten Typs entgegen nimmt. Dies ist ja bereits mit PHP möglich, auch wenn es noch kein vollständiges type hinting unterstützt (was ich persönlich bevorzugen würde).

                Geht aber nicht mit den doch deutlich öfter verwendeten skalaren Datentypen.

                Fehlerbehandlung ist Sache der Programmteile. Dafür kann es sinnvollerweise keinen globalen Mechanismus geben. Zu vielfältig sind mögliche Ursachen und Reaktionen.
                Ok, da habe ich mich falsch ausgedrückt. Bei mir werden im Bootstrap-Prozess mittels set_error_handler() und set_exception_handler() die Klassen initialisiert, die "aufgefangene" Fehler verarbeiten und je nach Umgebung (development, testing, production) unterschiedlich handeln.

                Ja, als allerletzte Möglichkeit für nicht vorhergesehene Fehler. Letzlich sollte jedoch das Ziel sein, dass dieses Auffangbecken niemals benutzt werden muss, und die Anwendung von sich aus mit den Fehlersituationen umgehen kann. Der allgmeine Error-Handler kann ja eigentlich nur das Script abbrechen, weil er nicht weiß, welche Konsequenzen ein Fortsetzen haben kann. Und Abbrechen sieht in der Regel unschön aus Anwendersicht aus.

                Ein Fehlerlogging-Mechanismus sollte unabhängig von der Anwendung arbeiten. [und alle Fehler protokollieren können] Also sollte der Loggingmechanismus (wenn nicht schon außerhalb PHPs konfiguriert) als eine der ersten Amtshandlungen des BS initialisiert werden.
                Das mache ich erst im Bootstrapping, da mir erst hier die Konfigurationsdaten zur Verfügung stehen (in einer ini-Datei steht beispielsweise, wo sich das error-log befindet).
                Da besteht, Deinem vorherigen Absatz nach zu urteilen, allerdings Nachholbedarf. Ich sollte es wohl ganz an den Anfang der Anwendung packen.

                In den BS-Teil würde ich nur allgemeine Dinge nehmen, die man mehr oder weniger für jede Anwendung braucht. Anwendungsspezifisches, wie Plugin-Initialisierungen oder DB-Layer-Konfiguration würde ich in den anwendungsspezifischen Teil bringen, also als Aufgabe des FC.

                Wenn du allerdings Skalierbarkeit wie beim HMVC-Ansatz als ein Ziel hast, solltest du dir überlegen, ob du diese Anhängigkeiten vom FC (und BS) nicht lieber beseitigst.

                Lo!

                1. Hey dedlfix,

                  Hierbei ist es so, dass die Klasse lediglich den Namen einer Datenbank-Tabelle enthält.

                  Ja, das ist aber nur der einfachste Anwendungsfall. Du hast mit der Klasse nun die Möglichkeit weitere Funktionalität hinzuzufügen.

                  prinzipiell ja (siehe aber bitte auch den nächsten Absatz).

                  Zend_Db_Table_Abstract stellt ja seine Funktionalität mehr oder weniger auf allgemeinem Level zur Verfügung. In deiner konkreten abgeleiteten Klasse kannst du nun Methoden hinzufügen, die beispielsweise den Code für bestimmte Abfragen enthalten. Und somit hast du nicht nur Overhead sondern einen Mehrwert.

                  prinzipiell auch hier ja. Allerdings ist das meiner Meinung nach im speziellen Falle des Zend-Frameworks nicht so sinnvoll, da dort vorgeschlagen wird, man solle die Datenbank-Abfragen, etc. (also zusätzliche Funktionalität) in einem Mapper machen. Damit bräuchte ich die Db_Table nicht mehr erweitern.

                  Wie bereits gesagt, bei den vorhandenen Frameworks haben sich viele Leute lange Zeit Gedanken drüber gemacht, aber meine derzeit (vielleicht naive) Meinung ist, dass man dies alles wesentlich "schlanker" gestalten könnte.

                  Ja, sicher. Man kann jedoch auch einfach die Teile ignorieren, die man nicht benötigt. Sie zu löschen ist wegen irgendwelcher Abhängigkeiten vielleicht keine gute Idee. Wenn man das aber gefahrlos hinbekäme, würde auch das Framework wieder schlanker wirken.

                  Das stimmt wohl, ändert aber nichts an den sehr umfangreichen Klassen an sich. Aber, das hatte ich ja bereits gesagt, wirst Du recht haben, dass man nach und nach zu eben jenem Punkt kommt.

                  Und eine abgeleitete Klasse nur wegen eines Tabellen-Namens? Für mich ist dies nach meinem OOP-Verständnis zwar folgerichtig, geht allerdings etwas zu weit.

                  Das ist lediglich die Grundlage. Aber auch in dieser einfachsten Form kann das schon von Vorteil sein, denn man hat nun einen eindeutigen Klassennamen, den man für Type Hinting verwenden kann.

                  Da habe ich noch gar nicht drüber nachgedacht. Das ist wirklich ein guter Punkt!

                  Außerdem, der Punkt fällt mir grad noch ein: Die aktuell mir bekannten Frameworks bieten viele, ich nenne sie mal "Komfort-Methoden", die meiner Meinung nach nicht sein müssten.

                  Kommt drauf an. Ich hab in meinem Haus einen Aufzug, den ich nicht verwende, weil ich zu Fuß meist schneller in der vierten Etage bin. Dennoch ist er beispielsweise für Lasten wie Einkäufe nützlich und ich würde ungern in ein Haus ohne Aufzug ziehen. (Schon für einen Umzug ist er eine enorme Erleichterung.)

                  Schön beschrieben! :-)

                  So kann ich einen beispielsweise einen DB-SELECT direkt als SQL-Statement ausführen oder die Funktion select()->from()->was-auch-immer ausführen.

                  Dazu musst du aber den konkreten SQL-Dialekt beherrschen, wissen, wie man im Speziellen Quotierungen und Maskierungen vornimmt - im Allgemeinen also eine Menge Wissen über das DBMS mitbringen. Das ist eigentlich nicht verkehrt, aber wenn du mehr der Programmierer als der Datanbankspezialist bist, wirst du vermutlich mit den Abstrahierungen des Layers besser zurecht kommen - weil sie, wenn sie gut umgesetzt wurden, doch eher aus der Programmierersicht denn aus DB-Admin-Sicht funktionieren.

                  Das sehe ich ein. Kurze andere Frage: PDO vs. Zend-Db? Kann mir jemand kurz und knapp sagen, warum ich das eine oder das andere favorisieren sollte? Im Endeffekt baut Zend-Db doch nur PDO nach, oder?
                  Ich nutze zur Zeit ausschließlich PDO. Oder besser gesagt: Eine eigene Datenbank-Klasse, die PDO erweitert.

                  Hinzu kommen viele Factory-Methoden (oder Konstruktoren), die ein Objekt, ein Array, einen String oder einen Integer entgegen nehmen können und innerhalb dieser Methode dann entscheiden, "was ich gemeint habe".

                  Ja, das ist der PHP-Weg. Geht nicht anders bei der Art der Typisierung. In typsicheren Sprachen (wie C#) sieht der Kompiler, welche der überladenen Methoden zum übergebenen Typ passt und ruft diese gezielt auf. PHP muss/[kann erst] zur Laufzeit ermitteln, welcher Typ vorliegt und dann unterschiedlich handeln.

                  Ich meinte eigentlich etwas anderes: Ein Beispiel, was ich mit "Komfort-Methoden" meine. Sagen wir, ich möchte ein Plugin laden. Das kann ich so laden

                    
                  $plugin = new Plugin_Test();  
                  $application->loadPlugin('test');  
                  $application->loadPlugin(0);  
                  $front->loadPlugin('test');  
                  $front->loadPlugin(0);  
                  $front->plugin->test;  
                  $config->plugin->test;  
                  
                  

                  und so weiter. Auch wenn das überspitzt ist, lade ich in alle der vorherigen Fälle das gleiche Plugin (Voraussetzung: Das Plugin namens "test" ist im Stack an Stelle 0).
                  Mein Problem hierbei ist, dass ich es an verschiedenen Stellen der Anwendung immer wieder anders machen könnte, sodass es nachher unübersichtlich wird. So habe ich zum Beispiel vergessen, wie etwas gemacht wird und schaue in der Doku nach. Dort kann ich mir irgendeinen Fall raussuchen. Der nächste, der dann den Quellcode sieht, versteht dann doch "die Welt nicht mehr".
                  Noch schlimmer dürfte es werden, wenn mehrere Entwickler am gleichen Projekt arbeiten.
                  Ich hoffe, es ist einigermaßen rübergekommen, was ich meine.

                  Mir würde es (in den meisten Fällen) vollkommen reichen, wenn eine Methode ein Objekt eines bestimmten Typs entgegen nimmt. Dies ist ja bereits mit PHP möglich, auch wenn es noch kein vollständiges type hinting unterstützt (was ich persönlich bevorzugen würde).

                  Geht aber nicht mit den doch deutlich öfter verwendeten skalaren Datentypen.

                  Ja, leider. Aber auch hier meinte ich - wenn auch etwas verunglückt ausgedrückt - das gleiche wie im vorherigen Absatz.

                  Fehlerbehandlung ist Sache der Programmteile. Dafür kann es sinnvollerweise keinen globalen Mechanismus geben. Zu vielfältig sind mögliche Ursachen und Reaktionen.
                  Ok, da habe ich mich falsch ausgedrückt. Bei mir werden im Bootstrap-Prozess mittels set_error_handler() und set_exception_handler() die Klassen initialisiert, die "aufgefangene" Fehler verarbeiten und je nach Umgebung (development, testing, production) unterschiedlich handeln.

                  Ja, als allerletzte Möglichkeit für nicht vorhergesehene Fehler. Letzlich sollte jedoch das Ziel sein, dass dieses Auffangbecken niemals benutzt werden muss, und die Anwendung von sich aus mit den Fehlersituationen umgehen kann. Der allgmeine Error-Handler kann ja eigentlich nur das Script abbrechen, weil er nicht weiß, welche Konsequenzen ein Fortsetzen haben kann. Und Abbrechen sieht in der Regel unschön aus Anwendersicht aus.

                  Das ist richtig. Kann ich nichts mehr hinzufügen :-)

                  In den BS-Teil würde ich nur allgemeine Dinge nehmen, die man mehr oder weniger für jede Anwendung braucht. Anwendungsspezifisches, wie Plugin-Initialisierungen oder DB-Layer-Konfiguration würde ich in den anwendungsspezifischen Teil bringen, also als Aufgabe des FC.

                  Wie zuvor schon: Das beantwortet meine Frage. Dahingehend muss ich meine Entwürfe noch einmal überarbeiten.

                  Wenn du allerdings Skalierbarkeit wie beim HMVC-Ansatz als ein Ziel hast, solltest du dir überlegen, ob du diese Anhängigkeiten vom FC (und BS) nicht lieber beseitigst.

                  Ja, das muss ich mir wirklich überlegen. Aber so ganz sicher bin ich mir im Moment noch nicht. Schön wäre es natürlich, wenn Abhängigkeiten möglichst vermieden werden. Das ist auch mein Ziel. Wie ich aber die Abhängigkeiten von BS und FC beseitigen könnte, ist mir grad noch - trotz des guten Artikels - ein Rätsel.

                  Gruß, Dennis

                  1. Hi!

                    Kurze andere Frage: PDO vs. Zend-Db? Kann mir jemand kurz und knapp sagen, warum ich das eine oder das andere favorisieren sollte? Im Endeffekt baut Zend-Db doch nur PDO nach, oder?

                    Bei PDO ist man auf die Implementationen in PHP angewiesen. Zend_Db muss aber nicht nur auf PDO aufsetzen. Es könnte auch direkt mysqli supporten (tut's ja auch) oder irgendwelche anderen in PDO nicht enthaltenen DBMSe. Außerdem fügt sich Zend_Db viel besser als PDO in das ZF ein, weil es ja direkt nach den ZF-Coding-Style-Richtlinien entworfen wurde. Auf PDO hat man da (theoretisch) keinen Einfluss.

                    Man hat ja damals mit PDO angefangen, weil man sich so die einzelnen Adapter für die verschiedenen DBMSe sparen konnte. Vermutlich war man damit teilweise nicht so glücklich und/oder performant, so dass man dann doch noch separate Adapter hinzugefügt hat.

                    Ich nutze zur Zeit ausschließlich PDO. Oder besser gesagt: Eine eigene Datenbank-Klasse, die PDO erweitert.

                    Damit machst du ja sowas ähnliches wie Zend_Db mit PDO.

                    Ein Beispiel, was ich mit "Komfort-Methoden" meine. Sagen wir, ich möchte ein Plugin laden. Das kann ich [auf verschiedene Weisen] laden [...]. Auch wenn das überspitzt ist, lade ich in alle der vorherigen Fälle das gleiche Plugin [...].
                    Mein Problem hierbei ist, dass ich es an verschiedenen Stellen der Anwendung immer wieder anders machen könnte, sodass es nachher unübersichtlich wird.

                    Das liegt in deiner Verantwortung als Programmierer. Ob es sinnvoll ist, dass sich das ZF nur auf eine Weise festlegt, wo doch viele Anwender unterschiedliche Wünsche haben können? Selbst wenn es nur eine Methode gäbe, könntest du noch genügend Inkonsistenzen in deine Anwendung einbauen.

                    Noch schlimmer dürfte es werden, wenn mehrere Entwickler am gleichen Projekt arbeiten.

                    Ja, aber da wirst du nur mit viel (Kommunikations)aufwand oder strengen Richtlinien alle in die selbe Spur bekommen. Auch hier musst du die Balance zwischen Konsistenz und zu vielen Einschränkung finden.

                    Lo!

                    1. Hey dedlfix,

                      Kurze andere Frage: PDO vs. Zend-Db? Kann mir jemand kurz und knapp sagen, warum ich das eine oder das andere favorisieren sollte? Im Endeffekt baut Zend-Db doch nur PDO nach, oder?

                      Bei PDO ist man auf die Implementationen in PHP angewiesen. Zend_Db muss aber nicht nur auf PDO aufsetzen. Es könnte auch direkt mysqli supporten (tut's ja auch) oder irgendwelche anderen in PDO nicht enthaltenen DBMSe. Außerdem fügt sich Zend_Db viel besser als PDO in das ZF ein, weil es ja direkt nach den ZF-Coding-Style-Richtlinien entworfen wurde. Auf PDO hat man da (theoretisch) keinen Einfluss.

                      guter Punkt!

                      Man hat ja damals mit PDO angefangen, weil man sich so die einzelnen Adapter für die verschiedenen DBMSe sparen konnte. Vermutlich war man damit teilweise nicht so glücklich und/oder performant, so dass man dann doch noch separate Adapter hinzugefügt hat.

                      War PDO dafür gedacht, sich die Adapter sparen zu können? Ich bin da drüber nicht informiert, dachte aber, PDO sei entwickelt worden um eine "reibungslose" Migration von einem zum anderen DB-System bei gleicher Syntax zu ermöglichen? Oder ist das das gleiche?
                      Sollte es nicht das gleiche sein, wäre das für mich sicher eine Überlegung wert PDO nicht zu verwenden, da dies ja wieder auf grundsätzliche Design-Fehler schließen lassen würde.

                      Ich nutze zur Zeit ausschließlich PDO. Oder besser gesagt: Eine eigene Datenbank-Klasse, die PDO erweitert.

                      Damit machst du ja sowas ähnliches wie Zend_Db mit PDO.

                      Vielleicht ja. An den Punkt, darüber nachzudenken, bin ich noch nicht gekommen. Allerdings wäre es dann hier wohl wieder der Fall, über den wir uns schon vorher unterhalten haben: Ich komme irgendwann dahin, dass meine Implementation der des bereits bestehenden (Zend-)Frameworks ähnelt und der Begriff "überladen" würde bei mir eine neue Bedeutung bekommen.

                      Ein Beispiel, was ich mit "Komfort-Methoden" meine. Sagen wir, ich möchte ein Plugin laden. Das kann ich [auf verschiedene Weisen] laden [...]. Auch wenn das überspitzt ist, lade ich in alle der vorherigen Fälle das gleiche Plugin [...].
                      Mein Problem hierbei ist, dass ich es an verschiedenen Stellen der Anwendung immer wieder anders machen könnte, sodass es nachher unübersichtlich wird.

                      Das liegt in deiner Verantwortung als Programmierer. Ob es sinnvoll ist, dass sich das ZF nur auf eine Weise festlegt, wo doch viele Anwender unterschiedliche Wünsche haben können? Selbst wenn es nur eine Methode gäbe, könntest du noch genügend Inkonsistenzen in deine Anwendung einbauen.

                      Ja, leider. Und genau dafür habe ich so eine Vorliebe... ;-)

                      Noch schlimmer dürfte es werden, wenn mehrere Entwickler am gleichen Projekt arbeiten.

                      Ja, aber da wirst du nur mit viel (Kommunikations)aufwand oder strengen Richtlinien alle in die selbe Spur bekommen. Auch hier musst du die Balance zwischen Konsistenz und zu vielen Einschränkung finden.

                      Wie überall im Leben: Die Waage! So, wie Du es schreibst, hört es sich so klar und richtig an. Aber, dass weißt Du ja auch, genau darin wird wohl die Kunst bestehen.

                      Danke und Gruß, Dennis

                      1. Hi!

                        Man hat ja damals mit PDO angefangen, weil man sich so die einzelnen Adapter für die verschiedenen DBMSe sparen konnte. Vermutlich war man damit teilweise nicht so glücklich und/oder performant, so dass man dann doch noch separate Adapter hinzugefügt hat.
                        War PDO dafür gedacht, sich die Adapter sparen zu können? Ich bin da drüber nicht informiert, dachte aber, PDO sei entwickelt worden um eine "reibungslose" Migration von einem zum anderen DB-System bei gleicher Syntax zu ermöglichen? Oder ist das das gleiche?

                        PDO ist wie einige andere Systeme auch, in erster Linie eine DBMS-Abstraktion, vor allem um den Zugriff auf die unterschiedlichen DBMSe zu vereinheitlichen. Ansonsten hast du ja in PHP nur die nativen DBMS-Funktionen, die sich in Umfang und Bedienweise recht erheblich voneinander unterscheiden. PEAR-DB war ein Versuch, mit PHP-Code den Mischmasch unter einer einheitlichen Oberfläche zu verstecken. Damals gab es noch kein PDO, weswegen da für jedes DBMS ein eigener Adapter/Driver gebaut werden musste. Das ZF konnte sich da zu Anfang schon auf PDO stützen und sich zunächst die individuellen Adapter sparen. Und auch jetzt sind nur einige wenige Adapter hinzugekommen - die anderen DBMSe muss man mit dem PDO-Adapter bedienen.

                        In der Praxis ist es meist deutlich weniger sinnvoll und überhaupt ein Anwendungsfall, zu einem anderen DBMS zu migrieren, als dieses immer als Argument für eine Abstraktionsschicht herhalten muss. Die Schichten, die sich unterhalb des Tabellen-Levels bewegen, sind hauptsächlich als Vereinheitlichung der Zugriffsweise zu sehen. Jedes DBMS spricht einen anderen SQL-Dialekt. Wenn man wirklich migrieren können will, muss man sich ziemlich in der verwendbaren Syntax einschränken. Man nivelliert damit alle Systeme auf einen sehr niedrigen Wert hinunter. Auf ein anderes System zu wechseln, bringt nur noch dann einen Vorteil, wenn sich Kosten sparen lassen oder bei ähnlich allgemeinen Gegebenheiten. Der bessere/andere Funktionsumfang kann dann nicht mehr genutzt werden.

                        Sollte es nicht das gleiche sein, wäre das für mich sicher eine Überlegung wert PDO nicht zu verwenden, da dies ja wieder auf grundsätzliche Design-Fehler schließen lassen würde.

                        PDO und jede andere Abstraktion kannst du verwenden, wenn es dir wert ist, eine einheitliche Oberfläche zu bekommen, dafür aber deren Overhead und den teilweise geringeren Funktionsumfang eines nativen Treibers in Kauf zu nehmen.

                        Mein Problem hierbei ist, dass ich es an verschiedenen Stellen der Anwendung immer wieder anders machen könnte, sodass es nachher unübersichtlich wird.
                        Das liegt in deiner Verantwortung als Programmierer. Ob es sinnvoll ist, dass sich das ZF nur auf eine Weise festlegt, wo doch viele Anwender unterschiedliche Wünsche haben können? Selbst wenn es nur eine Methode gäbe, könntest du noch genügend Inkonsistenzen in deine Anwendung einbauen.
                        Ja, leider. Und genau dafür habe ich so eine Vorliebe... ;-)

                        Wie heißt es so schön: Es ist noch kein Meister vom Himmel gefallen. Jeder, auf den du jetzt (noch) aufblicken kannst, hat ähnliche Leichen im Keller, garantiert.

                        Lo!

                        1. Hey dedlfix,

                          Mein Problem hierbei ist, dass ich es an verschiedenen Stellen der Anwendung immer wieder anders machen könnte, sodass es nachher unübersichtlich wird.
                          Das liegt in deiner Verantwortung als Programmierer. Ob es sinnvoll ist, dass sich das ZF nur auf eine Weise festlegt, wo doch viele Anwender unterschiedliche Wünsche haben können? Selbst wenn es nur eine Methode gäbe, könntest du noch genügend Inkonsistenzen in deine Anwendung einbauen.
                          Ja, leider. Und genau dafür habe ich so eine Vorliebe... ;-)

                          Wie heißt es so schön: Es ist noch kein Meister vom Himmel gefallen. Jeder, auf den du jetzt (noch) aufblicken kannst, hat ähnliche Leichen im Keller, garantiert.

                          Auch wenn's sich blöd anhört: Das freut mich immer wieder zu hören, dass es nicht nur mir so geht.

                          Zum Rest Deines Beitrags kann ich nichts mehr sagen, außer dass ich sehr gut und aufschlussreich finde.

                          Danke, Dennis

  2. Nun zu meiner Frage: Gehört das Routing in den Bootstrap-Prozess oder ist es die Aufgabe des Front-Controllers, dies zu übernehmen?

    Bisher rief mein Front-Controller eine Routing-Klasse auf, in der wiederum verschiedene Router (und diese konnten wiederum verschiedene Routen beinhalten) ausgeführt wurden.

    Allerdings erscheint mir das nicht mehr ganz so stimmig: Der Front-Controller sollte doch eigentlich nur ein "vollständiges", also bereits geroutetes (gibt's dieses Wort eigentlich?) Request-Objekt bekommen und eine Antwort zurückgeben?

    Ich hab den Artikel noch nicht fertig gelesen, aber er ich glaube er könnte für deine Frage hilfreich sein: http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/

    Struppi.

    1. Hey Struppi,

      auch Dir vielen Dank für Deine Antwort.

      Ich hab den Artikel noch nicht fertig gelesen, aber er ich glaube er könnte für deine Frage hilfreich sein: http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/

      Ich hab den Artikel grad nur kurz überflogen. Sieht sehr gut aus! Es ist aber schon zu spät, dass ich mir den jetzt richtig durchlesen und auch verstehen kann. Ich mache das morgen in Ruhe und melde mich dann diesbezüglich,

      danke Dir aber nochmal und wünsche eine gute Nacht!

      Dennis

      1. Hi!

        http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/
        Ich hab den Artikel grad nur kurz überflogen. Sieht sehr gut aus! Es ist aber schon zu spät, dass ich mir den jetzt richtig durchlesen und auch verstehen kann. Ich mache das morgen in Ruhe und melde mich dann diesbezüglich,

        Wenn du nun seinen Grundgedanken erkannt hast, wirst du festgestellt haben, dass der dort beschriebene Ansatz vor allem für Anwendungen geeignet ist, die skalieren müssen. Wenn du das garantiert nicht benötigst - vielleicht, weil du nur was kleines für dich selbst erstellst oder das Ziel eine Intranetanwendung mit bekannter Maximalbesucherzahl ist - hast du wieder Overhead dabei. Allerdings kannst du auch aus dem auf relativ einfaches Skalieren ausgelegten Aufbau mitnehmen, dass es von Vorteil ist, dass die einzelnen Aufgaben (Teil-MVCs) soweit voneinander abgegrenzt sind, dass sie eigenständig existieren können, was die Vorraussetzung für ein einfaches Umziehen auf eine andere, leistungsstärkere Umgebung ist. Wenn du von vorn herein diese Trennung im Hinterkopf behältst, und das Prinzip der klaren Abgrenzungen stets umzusetzen versuchst, sammelst du einerseit Erfahrung, andererseits fällt es leichter, eine bestehende Anwendung mit wenig Aufwand zu ändern, wenn doch mal die Skalierung benötigt wird. Andererseits kannst du dann mit hoffentlich wenig Änderungen auch das eigentlich nicht skalierende Framework als Grundlage für ein skalierendes Projekt verwenden.

        Wenn du ein eierlegendes Wollmich-Framework erstellen willst, wirst du sicher merken, dass es gar nicht so einfach ist, die Balance zwischen Features und Überladung zu halten.

        Lo!

        1. Hey Struppi, hey dedlfix,

          http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/

          hab mir den Artikel grad durchgelesen. Hört sich interessant an, aber so ganz verstehe ich ehrlich gesagt noch nicht den Unterschied zwischen dem dort beschriebenen H-MVC und dem modular aufgebauten, "normalen" MVC (was ja das Ziel sein sollte).
          In beiden Fällen versuche ich doch, möglichst autonome Teilbereiche einer Anwendung sicherzustellen, damit ich es später einfach wiederverwenden kann? Oder habe ich dem Artikel einen wichtigen Punkt nicht gelesen bzw. nicht verstanden?

          Wenn du nun seinen Grundgedanken erkannt hast, wirst du festgestellt haben, dass der dort beschriebene Ansatz vor allem für Anwendungen geeignet ist, die skalieren müssen. Wenn du das garantiert nicht benötigst - vielleicht, weil du nur was kleines für dich selbst erstellst oder das Ziel eine Intranetanwendung mit bekannter Maximalbesucherzahl ist - hast du wieder Overhead dabei.

          Nur ganz kurz hierzu: Dass es eigentlich immer Overhead gibt, weiß ich. Und für mich stellt es auch kein Problem dar und ich bin auch trotz geringen Overheads OOP-Fan, da für mich die anderen Vorteile klar überwiegen. Nur nicht, dass man mich falsch verstanden hat :-)

          Allerdings kannst du auch aus dem auf relativ einfaches Skalieren ausgelegten Aufbau mitnehmen, dass es von Vorteil ist, dass die einzelnen Aufgaben (Teil-MVCs) soweit voneinander abgegrenzt sind, dass sie eigenständig existieren können, was die Vorraussetzung für ein einfaches Umziehen auf eine andere, leistungsstärkere Umgebung ist.

          Dann hab ich den Artikel wohl doch einigermaßen verstanden.

          Wenn du ein eierlegendes Wollmich-Framework erstellen willst, wirst du sicher merken, dass es gar nicht so einfach ist, die Balance zwischen Features und Überladung zu halten.

          Das kann ich mir gut vorstellen. Hatte ja in einem anderen Beitrag schon geschrieben, dass es vielleicht etwas naiv ist zu glauben, man könnte das einfach besser machen.

          Gruß, Dennis

          1. Hi!

            http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/
            hab mir den Artikel grad durchgelesen. Hört sich interessant an, aber so ganz verstehe ich ehrlich gesagt noch nicht den Unterschied zwischen dem dort beschriebenen H-MVC und dem modular aufgebauten, "normalen" MVC (was ja das Ziel sein sollte).
            In beiden Fällen versuche ich doch, möglichst autonome Teilbereiche einer Anwendung sicherzustellen, damit ich es später einfach wiederverwenden kann? Oder habe ich dem Artikel einen wichtigen Punkt nicht gelesen bzw. nicht verstanden?

            HMVC geht noch einen Schritt weiter als das herkömmliche MVC. Es gibt nicht nur einen Haufen mit allen für die Anwendung benötigten Models, einen Haufen Controller und einen Haufen Views. Denn das Problem beim Verschieben von Funktionalität auf andere Server ist, dass du - um nur mal die Models zu betrachten - aus dem Haufen Models nicht exakt die zur Aufgabe passenden Teile bekommst, weil möglicherweise diese Models von mehreren Controller-Actions benötigt werden.

            Beispielsweise stellt das Model "User" Daten über Benutzer bereit. Dieses Model wird von den Actions X, Y und Z benötigt. Action Z soll nun aber ausgelagert werden, weil sie zu viele Ressourcen benötigt. Bei HMVC ist das alles so angelegt, dass du problemlos mit einem Griff die Action Z vom alten Server wegnehmen kannst, ohne dass den anderen nun Teile fehlen.

            Jede separierbare Teilaufgabe residiert in ihrer eigenen MVC-Umgebung und zwischen den M, V und Cs der anderen Teilaufgaben gibt es keine Verbindung.

            Lo!

            1. Hey dedlfix,

              Jede separierbare Teilaufgabe residiert in ihrer eigenen MVC-Umgebung und zwischen den M, V und Cs der anderen Teilaufgaben gibt es keine Verbindung.

              das grundsätzliche Prinzip dahinter versteh ich dank Deiner Ausführung jetzt. Aber frage ich mich gerade, wie es dabei mit der Wartbarkeit aussehen würde? Wenn jedes System insgesamt unabhängig ist, es aber verschiedene Methoden gibt, die von vielen verschiedenen "Mini-MVCs" genutzt werden sollen, müsste ich dann eine Änderung nicht in allen Teilen ändern?
              Wo ich mir das gerade geschriebene durchlese, hab ich vielleicht doch nicht das Prinzip verstanden...

              Gruß, Dennis

              1. Hi!

                Jede separierbare Teilaufgabe residiert in ihrer eigenen MVC-Umgebung und zwischen den M, V und Cs der anderen Teilaufgaben gibt es keine Verbindung.
                [...] Aber frage ich mich gerade, wie es dabei mit der Wartbarkeit aussehen würde? Wenn jedes System insgesamt unabhängig ist, es aber verschiedene Methoden gibt, die von vielen verschiedenen "Mini-MVCs" genutzt werden sollen, müsste ich dann eine Änderung nicht in allen Teilen ändern?

                Ja, hier hat man ganz sicher einige Code-Teile mehrfach rumliegen. Das lässt sich aber auch prinzipell nicht vermeiden, wenn man die Aufgaben auf mehrere physikalische Maschinen verteilen will. Das ist dann der Preis der einfachen Skalierbarkeit dieses Ansatzes.

                Während der Entwicklung wird man vermutlich meistens nur eine Kopie des gesamten Projekts bearbeiten und diese dann im Versionsverwaltungssystem einchecken. Ich denke, man kann den Code da schon irgendwie kennzeichnen, so dass man auf den produktiven Maschinen dann jeweils aufgabenweise exportieren kann. Andererseits dürfte es auch nicht stören, wenn man jeweils das gesamte Projekt auf die Produktivmaschinen bringt und davon dann nur den Teil anspricht, der dort erledigt werden soll. So kann man lediglich durch Konfigurationsänderung auf dem Master die Aufgaben neu verteilen, ohne die jeweils exportierten Code-Teile berücksichtigen zu müssen.

                Lo!

                1. Hey dedlfix,

                  sorry, hat diesmal was länger gedauert, bis ich jetzt zurückschreiben kann, aber es gibt doch tatsächlich noch ein Leben außerhalb des Netz' ;-)

                  [...] Aber frage ich mich gerade, wie es dabei mit der Wartbarkeit aussehen würde? Wenn jedes System insgesamt unabhängig ist, es aber verschiedene Methoden gibt, die von vielen verschiedenen "Mini-MVCs" genutzt werden sollen, müsste ich dann eine Änderung nicht in allen Teilen ändern?

                  Ja, hier hat man ganz sicher einige Code-Teile mehrfach rumliegen. Das lässt sich aber auch prinzipell nicht vermeiden, wenn man die Aufgaben auf mehrere physikalische Maschinen verteilen will. Das ist dann der Preis der einfachen Skalierbarkeit dieses Ansatzes.

                  So, wie ich mir das gerade überlege, dürfte das ja aber ein vergleichsweise kleiner Preis sein.

                  Während der Entwicklung wird man vermutlich meistens nur eine Kopie des gesamten Projekts bearbeiten und diese dann im Versionsverwaltungssystem einchecken.

                  Das klingt logisch, aber das sollte man doch eigentlich bei jedem Projekt so machen, oder? Sonst kommt man ja zwangsweise zu einem Problem wie in einem vorherigen Thread von mir, wo ich ja im Endeffekt mit zwei verschiedenen Versionen gearbeitet habe und eine davon fehlerhaft war.

                  Ich denke, man kann den Code da schon irgendwie kennzeichnen, so dass man auf den produktiven Maschinen dann jeweils aufgabenweise exportieren kann.

                  Wahrscheinlich schon. In einem "klassischen" MVC kann ich ja auch einzelne Module exportieren. Und im übertragenen Sinne ist ja eine Aufgabe im H-MVC für mich auch ein Modul.

                  Andererseits dürfte es auch nicht stören, wenn man jeweils das gesamte Projekt auf die Produktivmaschinen bringt und davon dann nur den Teil anspricht, der dort erledigt werden soll. So kann man lediglich durch Konfigurationsänderung auf dem Master die Aufgaben neu verteilen, ohne die jeweils exportierten Code-Teile berücksichtigen zu müssen.

                  So würde ich persönlich das wohl machen. Einziges Problem an der ganzen Geschichte wäre für mich, dass auch alle Einheiten von allen Beteiligten immer auf dem neuesten Stand gehalten werden. Aber das ist ein eigenes Thema.

                  Gruß, Dennis