Warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: SELECT * FROM variable in /var/www/web1030/html/mkernel.de/includes/database.mysql.inc on line 128

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 726

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 727

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 728

Warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 729
[Coder's Concept] Plugin-Architektur (v 1.0) | Drupal

[Coder's Concept] Plugin-Architektur (v 1.0)

  • warning: Cannot modify header information - headers already sent by (output started at /var/www/web1030/html/mkernel.de/includes/database.mysql.inc:128) in /var/www/web1030/html/mkernel.de/includes/common.inc on line 148.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: UPDATE variable SET value = 'a:17:{i:0;i:62;i:1;i:61;i:2;i:59;i:3;i:31;i:4;i:30;i:5;i:29;i:6;i:24;i:7;i:21;i:8;i:15;i:9;i:14;i:10;i:11;i:11;i:7;i:12;i:6;i:13;i:5;i:14;i:3;i:15;i:2;i:16;i:1;}' WHERE name = 'menu_masks' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 609.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: UPDATE variable SET value = 'a:0:{}' WHERE name = 'menu_expanded' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 609.
  • user warning: Table './usr_web1030_3/variable' is marked as crashed and should be repaired query: DELETE FROM variable WHERE name = 'menu_rebuild_needed' in /var/www/web1030/html/mkernel.de/includes/bootstrap.inc on line 634.

Wenn ein Blogeintrag mit [Coder's Concept] beginnt, werden Softwarekonzepte erläutert und beschrieben ohne auf eine Programmiersprache zurückzugreifen. Den Anfang macht das Thema Plugin-Architektur. An einem ausgedachten Beispiel mache ich deutlich, welche Vor- und Nachteile eine Plugin-Architektur in der eigenen Anwendung hat und wie eine minmale Umsetzung strukturiert ist.

Wen's interessiert, weiterlesen. Wen nicht, einfach weitergehen.

Pluginabsierte Anwendungsentwicklung bietet einen Weg, Software lose zu koppeln und sie nachträglich zu erweitern ohne dass dafür der gesamte Quellcode der Software zur Verfügung stehen muss. Damit die dadurch zwangsläufig entstehenden Codebasen (Die Basis der Software und die der Plug-Ins) miteinander kommunizieren können, müssen Schnittstellen definiert werden. Es entstehen 3 Komponenten:

  • Die Basissoftware
  • Die Schnittstellen, an denen sich die Basis und die Plugins halten
  • Die Plug-Ins

Je nach Programmiersprache und Umgebung der Software kann der Schnittstellenteil sehr unterschiedlich ausfallen. Es kann sein, das die Schnittstellen lediglich über Dokumentation (z.B. bei PHP) definiert werden oder dass eine Schnittstellendefinition in Form eines Headers (z.B. bei C/C++ und objC) vorliegt.
Es gibt auch Fälle, bei denen die Schnittstelle selbst ebenfalls ein Projekt ist und in Form einer Bibliothek zur Verfügung steht. Letzteres ist bei .NET-basierten Anwendungen sehr oft der Fall.

Zur Verdeutlichung eine fiktive Situation: Joe, der Application Developer, baut gerade an einer kleinen Applikation. Sie ist Dokumentbasiert und jedes Dokument enthält eine Liste von Tasks. Task ist als Klasse implementiert mit den folgenden Eigenschaften:

  • Finished (bool)
  • Description (string)
  • Priority (int)

Joe's Kunde hat ihn gebeten, eine leicht erweiterbare Filterfunktion einzubauen. Nach Absprache mit seinem Kunden will Joe eine Plugin-Schnittstelle schaffen.

Er überlegt sich, wie er die Plugins von seiner Applikation aus ansprechen kann. Das Problem dabei ist, das die Plugins ja beim Übersetzen der Applikation nicht verfügbar sind, er dennoch Funktionen davon aufrufen will. Er kommt zu dem Schluss, eine Schnittstelle zu definieren.
(Platform note: wenn es Schnittstellen nicht gibt, dann eine Klasse oder besser eine abstrakte Klasse). Die Schnittstelle IFilter enthält folgende Elemente:

  • bool PassesFilter(Task obj)
  • string getName()
  • string getAuthor()

Nachdem er die Schnittstelle (oder abstrakte Klasse) definiert hat, will er ein neues Projekt in seiner Entwicklungsumgebung anlegen, und die Schnittstelle implementieren. Doch... er kann gar nicht auf die Schnittstelle zugreifen. Er lagert die Schnittstelle und die Klasse Task in eine Bibliothek "AppShared" aus und verwendet diese Bibliothek in dem neuen Plugin-Projekt.
(Platform note: bei einigen Sprachen wird hierfür der Header reichen, bei anderen muss auch der Code von Task verfügbar sein)

Er implementiert einen einfachen Testfilter, der bei PassesFilter wahr zurückgibt, wenn die Priorität des Tasks größer als 5 ist. Die dabei entstehende Bibliothek lädt nun seine Applikation automatisch und bietet dem Nutzer an, das Dokument damit zu filtern.
(Platform note: wie man die Plugins lädt, ist stark Platformspezifisch.)

Wir haben also eine Programmstruktur bestehend aus drei Projekten:

  • AppShared (Bibliothek)
  • App (Applikation)
  • Das Testplugin

"AppShared" enthält alle Klassen und Schnittstellen, die den Plugins zur Verfügung stehen. "App" dagegen ist die eigentliche Applikation.
Das hier beschriebene Plugin-Prinzip ist primitiv. Plugins können nicht miteinander und auch nicht mit der Applikation aktiv interagieren. Für die Aufgabenstellung ist es jedoch nicht notwendig. Wie eine Plug-In-Architektur aussieht ist demnach von den Anforderungen aus dem Umfeld abhängig.

Es folgen noch zwei Artikel, bei denen diese Architektur in Objective-C und in C# umgesetzt werden.