Tutorials » Erweiterung bestehender Funktionen
Erweiterung bestehender Funktionen
In der täglichen Arbeit tritt häufig die Situation auf, dass eine bestehende Bibliothek
die bisherigen Anforderungen erfüllt hat, der aktuell zu lösende Spezialfall jedoch nicht.
Viele Entwickler neigen in der geschilderten Situation dazu, die Funktion für den aktuellen
Anwendungsfall neu zu implementieren. Andere wiederum versuchen krampfhaft eine Bibliothek zu suchen,
die diesen Spezialfall abdeckt. Diese Möglichkeiten führt zwar sicher zum Ziel, verringern
jedoch entweder die Wartbarkeit, da weitere externe Bibliotheken eingebunden oder gar beliebig
kombiniert werden, und erhöhen dabei gleichzeit die Fehleranfälligkeit. Darüber hinaus
sollte sich jeder bewusst sein, dass eine API-Änderung automatisch bedeutet, sich vom
Update-Pfad der eingesetzten Bibliothek zu entfernen, da in einer Version eingefügte Quick-Hacks
womöglich in einer neueren Version nicht mehr funktionieren.
Dieses Tutorial möchte daher eine Methode aufzeigen, wie bestehende Funktionen ohne Anpassung
an der verwendeten Biblothek für den eigenen Bedarf "angepasst" und genutzt werden können.
Das Tutorial geht dabei davon aus, dass die behandelten Bibliotheken bzw. Module kein eigener Code
ist, da diese Methode sonst keinen Sinn macht.
Mancher Leser wird zurecht anmerken, dass eine Anpassung einer Bibliothek bedeutet, dass die Signatur
- die API der Bibliothek, oder des Moduls - nicht allgemeingültig genug ausgelegt ist. In vielen
Fällen muss ich dem Leser Recht geben, es gibt jedoch erfahrungsgemäß relativ viele
API-Definitionen, die nicht für exakt jeden Anwendungsfall mit genau einer Methode verwendbar
sind.
Das folgende Beispiel soll an Hand des im Release des Frameworks enthaltenen Moduls
socialbookmark zeigen, wie eine vorhandene Bibliothek für den eigenen Gebrauch
erweitert werden kann.
Die im
adventure-codepack-* enthaltenen Bibliotheken des Moduls, sehen die
Möglichkeit vor, dieses per XML-Tag in den Inhaltsbereich einzubinden. Dazu enthält das Modul
eine TagLib, deren Eigenschaften unter
Mitgelieferte Module,
Kapitel 5, beschrieben werden. Die Tagdefinition sieht dabei vor, dass ein Titel der aktuellen Seiten,
der beim Bookmarkservice als Linktitel verwendet wird, als Tag-Attribut übergeben werden kann.
Da die Definition jedoch statisch ist, ist es zunächst nicht möglich einen dynamischen Titel
an die TagLib zu übergeben. Gerade in einer CMS-Seite, in der der Titel abhängig der
anzuzeigenden Seite dynamisch variiert, ist das problematisch!
Um die aktuell mögliche Funktion zu analysieren, muss sich der Entwickler die Frage stellen:
"
Was ist schon möglich und was fehlt wirklich?". Im Fall des
Socialbookmarking-Moduls ist die Antwort denkbar einfach: statisches
Anzeigen der
Bookmark-Icons ist möglich,
dynamische Titel nicht!
Ein sehr beliebtes Mittel ist
Wrapping.
Wrapping in der Programmierung
bedeutet, eine weitere Schicht um eine Bibliothek - oder hier eine Taglib - zu legen und dadurch die
Funktionalität
ohne Veränderung der eingesetzten Komponente zu erweitern.
Betrachten wir zunächst die Funktionalität der bisherigen TagLib-Klasse. Diese implementiert
eine
transform()-Methode, die die Tag-Eigenschaften an den
socialbookmarkManager
übergibt und diesen für die Ausgabe der Bookmarking-Elemente verwendet. Der Quellcode der
Klasse (im
adventure-codepack-* zu finden unter
apps/modules/socialbookmark/pres/taglib)
wird im folgenden Kasten dargestellt (Kommentare wurden gekürzt):
PHP-Code
class social_taglib_bookmark extends Document {
function social_taglib_bookmark(){
$this->__Attributes['width'] = '20';
$this->__Attributes['height'] = '20';
$this->__Attributes['title'] = null;
$this->__Attributes['url'] = null;
$this->__Attributes['target'] = null;
}
function transform(){
// Bookmark-Manager holen
$sBM = &$this->__getServiceObject('modules::socialbookmark::biz','socialBookmarkManager');
// Breite und Höhe konfigurieren
$sBM->set('Width',$this->__Attributes['width']);
$sBM->set('Height',$this->__Attributes['height']);
// URL-Parameter konfigurieren
if($this->__Attributes['url'] != null){
$sBM->set('URL',$this->__Attributes['url']);
// end if
}
if($this->__Attributes['title'] != null){
$sBM->set('Title',$this->__Attributes['title']);
// end if
}
if($this->__Attributes['target'] != null){
$sBM->set('Target',$this->__Attributes['target']);
// end if
}
// Bookmark-Quelltext zurückliefern
return $sBM->getBookmarkCode();
}
}
Um den Titel der aktuell angezeigten Seite dynamisch zu gestalten, ist es nun ratsam, eine weitere
TagLib zu definieren, die ausschließlich die neue Funktionalität beinhaltet, jedoch Gebrauch
der bereits bestehenden Funktion macht. Um ein konkretes Beispiel aufzeigen zu können, soll der
neu zu erstellende Tag
my:bookmark genannt werden. Wie im Tutorial
TagLibs erstellen beschrieben,
ergibt sich dadurch der Klassenname
my_taglib_bookmark. Diese beinhaltet dann
folgenden Quellcode:
PHP-Code
import('modules::socialbookmark::pres::taglib','social_taglib_bookmark');
class my_taglib_bookmark extends social_taglib_bookmark {
function my_taglib_bookmark(){
// Ausfuehren des Konstruktors der Eltern-Klasse
parent::social_taglib_bookmark();
}
function transform(){
// Beziehen des aktuellen Titels
$Title = /* Aktueller Titel */;
// Title in Tag-Attribut einsetzen
$this->__Attributes['title'] = $Title;
// Ausgabe mit Hilfe der Eltern-Methode transform() erzeugen
return parent::transform();
}
}
In der Methode
transform() wird dabei lediglich der Titel der Seite je nach
Anwendungsfall erzeugt und dem dafür vorgesehenen Attribut übergeben. Die eigentliche
Erzeugung der Ausgabe wird der bisherigen TagLib-Methode überlassen. Durch diese Änderung
bleibt es weiterhin möglich, dem Tag die Attribute
mitzugeben, ohne das Verhalten nochmals in der neuen Klasse implementieren zu müssen. Das
Einbinden der erweiterten TagLib funktioniert dann wie gewohnt mit
APF-Template
<core:addtaglib namespace="dein::namespace" prefix="my" class="bookmark" />
<my:bookmark width="16" height="16" />
Sollte die verwendete Bibliothek zukünftig eine andere API unterstützen, beschränkt
sich die Anpassung lediglich auf das Füllen des Attributes
title, da der interne
Ablauf der Methode
transform() unberührt bleibt. Weiterer Vorteil ist, dass die
API der Wrapper-Klasse konstant bleibt und keine Anpassung im Gesamtsystem zur Einbindung des Moduls
vorgenommen werden muss. Das in diesem Tutorial aufgezeigte Beispiel hat sich zwar "nur" auf die
Erweiterung einer TagLib beschränkt, das Prinzip ist jedoch auf andere Bereiche anwendbar.
Kommentare
Möchten Sie den Artikel eine Anmerkung hinzufügen, oder haben Sie ergänzende Hinweise? Dann können Sie diese
hier einfügen. Die bereits verfassten Anmerkungen und Kommentare finden Sie in der untenstehenden Liste.
Für diesen Artikel liegen aktuell keine Kommentare vor.