Spezifikation-components

< Bestandteile von Plugins | Plugin-Spezifikation 2.0 | Plugin-Versionsschema >

Integration/Komponentenarchitektur

Um das Problem zu lösen, Stud.IP an bereits vorhandenen Stellen, also in seiner Kernfunktionalität, zu erweitern, kommt die im folgenden beschriebene Komponentenarchitektur zum Einsatz.

Diese Architektur kann sinnbildlich so erklärt werden, dass Stud.IP aus einer Menge an Komponenten besteht.

Eine Komponente ist ein funktionales Subsystem, dass einen Service im Kontext von Stud.IP anbietet. Beispiele: ein Fotoalbum für Benutzer, ein Newsfeed-Aggregator, ein Prüfungssystem usw. Der Stud.IP-Kern soll in diesem Zusammenhang der Einfachheit halber als eine einzelne Komponente gelten.

Jeder dieser Komponenten hat die Möglichkeit, "Steckdosen" (Extension Points) anzubieten, in die sich wiederum andere Komponenten "einstöpseln" können. Das erlaubt es einer Komponente, die Funktionalität einer anderen zu erweitern, ohne dass die erweiterte Komponente überhaupt wissen muss, dass es diese sie erweiternde Komponente überhaupt gibt. Erforderlich ist nur, dass die eine Komponente ihre "Steckdosen" (Extension Points) zur Verfügung stellt und nutzt und andere Komponenten sich in diese "Steckdosen" (Extension Points) einstöpseln können.

Grundsätzlich bietet zuallererst nur das Kernsystem solche Extension Points an. Jedes weitere installierte Plugin erhält aber die Möglichkeit, eigene Extension Points hinzuzufügen.

§1.  Der Komponentenmanager

Extension Points werden in PHP durch Interfaces abgebildet. Damit wird eine Schnittstelle sichergestellt, über die beide Seiten kommunizieren können. Ein solches Komponenteninterface sieht beispielweise so aus:

  1. <?php
  2.  
  3. interface Studip_PortalComponent extends Studip_Component {
  4.  
  5.   function showOverview($unauthorizedview = TRUE);
  6.  
  7.   function hasAdministration();
  8.  
  9.   function hasUnauthorizedView();
  10.  
  11.   function hasAuthorizedView();
  12. }

Ein Komponenteninterface definiert eine Menge von Operationen, die eine Komponente ausführen können muss. (Beispiel: Einen Text für eine Box innerhalb der Stud.IP-Homepage liefern.)

Idealerweise werden Komponenteninterfaces eine feine Granularität aufweisen. Ein Gegenbeispiel ist das implizite Interface der alten Homepage-Plugins.

Komponenteninterfaces müssen ihrerseits das Markerinterface "Studip_Component" implementieren, damit der Komponentenmanager in die Lage versetzt wird, automatisch zwischen normalen Interfaces und Komponenteninterfaces unterscheiden zu können. Es ist ja immer möglich, dass eine Komponente auch Interfaces implementiert, die nichts mit der Komponentenarchitektur zu tun haben.

§2.  Komponenten

Komponenteninterfaces repräsentieren die "Steckdose", in die sich eine Komponente "einstöpseln" kann. Das "Einstöpseln" geschieht durch das Schreiben einer Klasse, die dieses Interfaces implementiert ("class ExampleComponent implements Studip_PortalComponent"). Ausserdem muss diese Klasse – die Komponente – beim weiter unten beschriebenen Komponentenmanager registriert werden.

§3.  Der Komponentenmanager

Der Komponentenmanager ist für zwei Aufgaben zuständig. Zum einen können bei ihm Komponenten angemeldet und abgemeldet werden, zum anderen kann man über ihn alle Komponenten erhalten, die ein bestimmtes Komponenteninterface ("Steckdose") implementieren, um dann an diesen die im Komponenteninterface deklarieren Methoden aufzurufen. Da man nur Komponenten erhält, die dieses Komponenteninterface implementieren, kann man sicher sein, dass diese Methoden auch tatsächlich zur Verfügung stehen, da der Compiler dieses zusichert.

Der Komponentenmanager definiert u.a. folgende Methoden:

  1. <?php
  2.  
  3. class Studip_ComponentManager {
  4.  
  5.   static function instance();
  6.  
  7.   function register($component);
  8.   function unregister($class);
  9.  
  10.   function components($interface_name, $filter = NULL);
  11.   function signal($interface_name, $method, $args = array());
  12. }

§3.1  Singleton-Instanz

Die Klassenmethode #instance liefert die Singleton-Instanz des Komponentenmanagers:

  1. $manager = Studip_ComponentManager::instance();

§3.2  Komponenten anmelden

An dieser Instanz kann dann eine Komponente mittels ihres Namens registriert werden:

  1. $manager = Studip_ComponentManager::instance();
  2. $manager->register('ExampleComponent');

Achtung: Es muss sichergestellt werden, dass der Quellcode der benannten Komponente bereits geladen ist. Da der Komponentenmanager die Komponente nicht untersuchen kann.

§3.3  Komponenten abmelden

Auf ähnliche Weise kann eine Komponente auch wieder beim Komponentenmanager abgemeldet werden:

  1. $manager = Studip_ComponentManager::instance();
  2. $manager->deregister('ExampleComponent');

Auch hier gilt, dass der Quellcode der Komponente geladen sein muss.

§3.4  Komponenten eines Komponenteninterfaces finden

Um alle Komponenten zu erhalten, die ein bestimmtes Komponenteninterface implementieren, sendet man #components an den Komponentenmanager:

  1. $manager = Studip_ComponentManager::instance();
  2. $components = $manager->components('ExampleComponent');
  3.  
  4. # use those components
  5. $result = array();
  6. foreach ($components as $component) {
  7.   $result[] = $component->exampleMethod(42);
  8. }
  9. [...]

§3.5  Mitteilung an alle Komponenten eines Komponenteninterfaces

Gelegentlich will man an allen Komponenten eines Komponenteninterfaces nur eine Methode aufrufen, ohne dass man deren Rückgabewert benötigen würde – wenn man den Komponenten also nur etwas "mitteilen" will. Für diesen Fall kann man #signal senden:

  1. $manager = Studip_ComponentManager::instance();
  2. $manager->signal('TodoComponent', 'todoAdded', array($arg1, $arg2, $arg3));

§4.  TODO

  • Die abstrakten Legacy-Plugins müssen diese implementieren. Vorteilhafterweise würde man dann nicht nur ein Komponenteninterface pro Legacy-Plugintyp haben, sondern viele. (Beispiel: Das Homepage-Plugin könnte und sollte >3 von solchen Komponenteninterfaces implementieren.)
  • Derzeit enthalten die Legacy-Plugins Zustand, über den Punkt, an dem sie eingebunden werden. So existieren zum Beispiel für das AbstractStudipStandardPlugin die Methoden #getId und #setId, die wohl die Veranstaltungs- bzw- Einrichtungs-ID enthalten. Dieser Zustand sollte - sofern nötig (vielleicht sollte man das immer machen?) - explizit als Parameter in den Methoden, die in den Komponenteninterfaces deklariert werden, vorgesehen sein.

Jedes Plugin-Paket muss genau eine Plugin-Klasse enthalten (siehe Bestandteile). Diese Plugin-Klasse...

< Bestandteile von Plugins | Plugin-Spezifikation 2.0 | Plugin-Versionsschema >

Letzte Änderung am 20.05.2008 13:07 Uhr von mlunzena.