Capabilities in Zikula - Module austauschen für spezielle Szenarien

in  Zikula Apps , ,

Capabilities in Zikula - Module austauschen für spezielle Szenarien

Wenn mehrere Zikula-Module zusammen arbeiten, wird dies in der Regel durch Modulabhängigkeiten ausgedrückt. Damit lässt sich festlegen, dass ein Modul A ein anderes Modul B entweder zwingenderweise voraussetzt oder optional empfiehlt. In größeren Systemen, die aus mehreren Modulen bestehen, reicht dies ab einem gewissen Punkt nicht mehr aus.

Austauschbarkeit von Modulen gewährleisten

Früher gab es in der Modultabelle von Zikula Flags für bestimmte Funktionen, zum Beispiel isProfile für Profilmodule und isMessaging für Module, die private Nachrichten verwalten können. In größeren Gesamtsystemen kommt es oft vor, dass man die Möglichkeit benötigt, so etwas allgemein für eigene Zwecke zu definieren.

Die grundlegende Anforderung besteht darin, einzelne Module einer zusammenhängenden Komponente austauschbar zu haben. Man kann zwar Meta-Admin-Module bauen, um bestimmte Aspekte eines großen Systems pro Kunde und Einsatz konfigurierbar zu machen. Ab einem bestimmten Punkt ist es aber nötig, einzelne Module für ein bestimmtes Projekt komplett auswechseln zu können. Zum Beispiel könnte man mehrere Produktstammmodule in einem Webshop-System haben. Oder es könnte notwendig werden, unterschiedliche Patientenmodule in einem medizinischen System zu realisieren, weil ein bestimmtes Projekt komplett andere Anforderungen stellt als vergleichbare frühere Projekte.

Module lose koppeln

Heute bietet Zikula dafür ganz allgemein die Möglichkeit, Capabilities zu nutzen. Mit diesen kann man die gewünschte Austauschbarkeit realisieren. Jedes Modul kann bestimmte Capabilities anbieten und nutzen beziehungsweise einfordern.

Praktisch definieren Capabilities damit eine Art Schnittstelle für Module: statt eine Abhängigkeit zu einem konkreten Modul zu setzen wird lediglich ausgedrückt, dass eine bestimmte Funktionalität benötigt wird. Welches Modul diese bereitstellt, ist flexibel. Die Module werden also nur noch lose gekoppelt, in der Konsequenz lassen sich beispielsweise in dem Modul MyShop alle Vorkommen des Moduls MyProducts ersetzen durch $myProductModule.

Capabilities anbieten und nutzen

Ein Modul kann die Capabilities, die es anbietet, einfach in der Versionsklasse definieren. Als Beispiel schaut es Euch einfach einmal hier im Profile-Modul an. Zikula persistiert diese Informationen in der Datenbank in einer eigenen Capabilities-Tabelle.

Zur Verwendung von Capabilities bietet die ModUtil-Klasse einige Einstiegspunkte.

1
2
3
ModUtil::isCapable($module, $capability)
ModUtil::getModulesCapableOf($capability = 'user')
ModUtil::getCapabilitiesOf($module)

Diese Hilfsmethoden kann man wie folgt verwenden:

1
2
3
4
$canDoProductManagement = ModUtil::isCapable('MyProductModule', 'productManagement');
$productModules = ModUtil::getModulesCapableOf('productManagement');
$capabilities = ModUtil::getCapabilities('MyProductModule');
echo 'MyProductModule bietet: ' . implode(', ', array_keys($capabilities));

Regeln für den Austausch

Damit die Module wirklich austauschbar werden, müssen sie bestimmte Dinge gleich regeln und sich nach außen hin (dem nutzenden Code gegenüber) gleich verhalten. Beispielsweise sollten Sie die Funktionen beziehungsweise APIs, die von außerhalb verwendet werden können, in gleicher Art und Weise anbieten und benennen. Idealerweise werden also Interfaces für diese Funktionen definiert, um festzulegen, wie ein Modul diese Vorgaben zu implementieren hat. Hier stellt sich die Frage, wo diese Interfaces am besten platziert werden. Eine Möglichkeit wäre es, sie im nutzenden Modul, zum Beispiel MyShop, unterzubringen, was jedoch die Wiederverwendbarkeit einschränken würde. Besser scheint es, die Schnittstellen in einem den genutzten Modulen übergeordneten Rumpfmodul, wie etwa MyProductBase, unterzubringen.

Weitere Überlegungen

Wir haben als Idee im Hinterkopf, Capabilities eventuell direkt in der DSL und im Generator von ModuleStudio zu unterstützen. So könnte man direkt im Anwendungsmodell definieren, welche Fähigkeiten ein Modul anbietet.

Statt Capabilities könnte man übrigens auch das Event-System von Zikula beziehungsweise Symfony einsetzen, um eine harte Kopplung zwischen mehreren Modulen abzulösen. Dies ist allerdings ein bisschen wie Kanonen auf Spatzen.