Vor wenigen Tagen wurde papayaCMS 5.0 veröffentlicht. Da eventuell der ein oder andere mit dem System nun herumexperimentiert, wird man als Entwickler auch schnell Module entwickeln wollen. Vor allem bei gröĂeren Modulen (bestehend aus vielen Ausgabe-Klassen) empfiehlt sich eine weit granulĂ€rere Aufteilung als zwingend vorgeschrieben ist.
Ich erspare mir die ErklĂ€rung der Basispapayasystems, dafĂŒr möge man bitte die entsprechenden Dokumentionen (PDF) konsultieren. Nur so viel sei gesagt: Um die Daten von der Datenbank auf den Bildschirm zu bekommen, braucht man grundsĂ€tzlich nur eine Ausgabeklasse (Seite, Box, usw.) und ein entsprechendes XSL-Template. Aber, aber..
Prinzipiell gilt: MVC-Kenner werden einen sehr leichten Einstieg haben, die anderen sollten bei Fragen zunÀchst diese Thematik verinnerlichen.
Damit eine Klasse Zugriff auf die Datenbank hat, muss es von base_db (sys_base_db.php) abgeleitet werden. Vor allem bei kleinen Seitenmodulen passiert es hĂ€ufig, dass der Entwickler die Kurzversion nimmt: Generalisierung der Datenbankklasse, 1-2 Queries und XML-Ausgabe. SpĂ€testens, wenn man die gleiche FunktionalitĂ€t – etwa “last blog post titles” – nicht nur als Seiten- sondern auch als Boxmodul benötigt, entsteht doppelte Code. Doppelter und redundanter Code. Schlecht. Ein guter Ansatz, um die ZustĂ€ndigkeiten zu prĂŒfen und zu ermitteln, ob Operationen sich nicht generalisieren und delegieren lassen können. Und ja, wir kommen dem Ziel MVC damit praktisch sehr nahe.
Alleine aus diesem praktische Grunde (und selbstverstĂ€ndlich ist die Verwendung von Delegation grundsĂ€tzlich in Modulsystem zu befĂŒrworten) empfiehlt sich der Einsatz einer Datenbasisklasse. Diese Klasse erweitert die o.g. Datenbankklasse, die Ausgabemodule instanziieren nur noch diese Basisklasse. Und fĂŒr unsere Freunde der notorischen Delegationsverweigerer: Mit “Seitenklasse erweitert Datenbankklasse” kommt ihr nicht weiter… und das gilt selbstverstĂ€ndlich auch fĂŒr alle anderen Arten von Modulen. TatsĂ€chlich ist hier Delegation unbedingt notwendig.
Ein weiterer Vorteil ist die bessere Wartbarkeit und Ăbersichtlichkeit (vgl. MVC). SelbststĂ€ndlich werden auch schreibene Operationen in dieser Klasse implementiert. Der Einsatz von Interfaces oder mehrerer Datenbasisklassen steht jedem frei. Man sollte aber nicht mit Kanonen auf Spatzen schieĂen, ein komplexes System wird durch mehr KomplexitĂ€t nicht wirklich einfacher.
Die weitere Aufgabe des Ausgabemoduls (vgl. Controller) ist natĂŒrlich auch die Ausgabe.. ja, kein Witz
Auch hier gibt es eine Ă€hnliche Konstellation wie bei den Datenbankabfragen, aber in der umgekehrten Sicht: Es gibt in gröĂeren System hĂ€ufig gleiche oder Ă€hnliche Ausgaben. Auch hier kann die Faulheit einen schnell dazu verleiten, den XML-Code im Controller selbst zu schreiben – ist ja praktisch. Aber auch hier gilt: SpĂ€testens wenn man selber [beim Refactoring] anfĂ€ngt, und klasseninterne Helpermethoden zur Sub-XML-Generierung zu bauen oder gleichen XML-Code an mehr als 1-2 Stellen verwendet.. richtig: Delegation! Hier empfiehlt sich der Einsatz einer Ausgabebasisklasse. Jene Klasse hat im Wesentlichen nur eine Aufgabe: FĂŒr einen oder mehrere Parameter (idR eine Datenarraystruktur) ein geschĂ€ftsklassenabhĂ€ngiges XML zu bauen. Es gibt weder eine Verbindung zur Datenbank noch zu anderen Ausgabemodulen.
Ebenfalls fĂŒr diese Klassen gilt: Eine weitere strukturelle Aufteilung der Ausgabebasisklassen kann, muss aber nicht vorteilhaft sein.
SelbstverstĂ€ndlich lassen sich beide Klasse auch in Nicht-Ausgabemodulen verwenden, etwa einem Connectormodul. Das ist vor allem fĂŒr Module interessant, die bestimmte Daten und/oder XML (aus welchen GrĂŒnden auch immer) weitergeben mĂŒssen.
Tipp 1: Vor allem bei mehreren Seiten- oder Boxmodulen kann es durchaus sinnvoll sein, eine gemeinsame Oberklasse (base_myplugin_content) zu erstellen. Hier lassen sich auch direkt die notwendigen Basisklassen korrekt instanziieren.
Tipp 2: Die Verwendung des Singleton-Pattern steht einem frei: In der Regel hat es aber wenig Sinn, die Datenbasisklasse mehrfach zu erstellen (kann vorkommen, wenn Boxen in Seiten des gleichen Modules auftauchen). Daher: getInstance().
In der Zusammenfassung:
- Trennung der ZustÀndigkeiten und Verwendung von Delegation, aber: Generalisierung geht auch
- Verwendung von Datenbasisklassen, bspw. base_myplugin_data extends base_db
- Verwendung von Ausgabebasisklassen, bspw. base_myplugin_output extends base_object
- delegierte Verwendung der o.g. Klassen in Seiten- und Boxmodulen











