"micokernel" Plugin-System zur Anwendungsentwicklu

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo zusammen,

gestern Abend machte ich mir Gedanken darüber, wie ich das Plugin-System meiner mittlerweile immer größer werdenden Audioplayers konsequenter umsetzen könnte.

Zur Zeit ist es so, dass erst die Fenster-Klasse und dann eine Hauptklasse initialisiert wird. Diese Hauptklasse lädt alle möglichen weitere Klassen, etwa für eine Datanbankanbindung, für Internetkommunikation, für Events und eben auch für meine Plugins.
Die meisten Erweiterungen, die ich nun noch an meinem Player vornehme, kommen als Plugins daher, die dynamisch eingebunden werden. So erhoffe ich mir, den Hauptcode zu entrümpeln und übersichtlicher zu gestalten. Deaktiviert man alle Plugins, ist der Player ziemlich schlank und "funktionslos".


Nun meine Überlegung: Eigentlich wäre es doch sinnvoll, statt der Hauptklasse bzw. des Fensters gleich das Plugin-System zu initialisieren. Dies könnte die Basis des Programmes sein und alle weiteren Klassen als Plugins nachladen - etwa das Fenster.
Ich verspreche mir dadurch eine noch deutlichere Struktur, die noch einfacher zu erweitern ist. Auch ließe sich so ggf. schnell ein anderes Toolkit einbinden - als z.B. QT statt GTK.
Für die Umsetzung habe ich mir überlegt, zwischen "essential" und "optional" Plugins zu unterscheiden. Essentielle Plugins können nicht deaktiviert werden und bilden die Basis des Programmes. Optionale Plugins wären die "klassichen" Plugins. Wie auch bei den meisten anderen Plugin-Systemen üblich, haben diese eine XML oder ähnliches, die fest legt, in welcher Reihenfolge das jeweilige Plugin gestartet wird. Ggf. ließe sich sogar ein Abhängigkeiten-System integrieren, das etwa ein Plugin nur dann lädt, wenn das benötigte "GTK" Plugin ebenfalls aktiviert wurde.

Nachteil dieser Methode ist sicher ein tendenziell größerer Overhead.

Da ich kein in diesem Bereich keine Erfahrungen habe und nicht weiß, welche "Schulen" es diesbezüglich in der Informatik gibt, wollte ich mal anfragen, was ihr davon haltet.

schöne Grüße,

Barabas
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Ich denke, Austauschbarkeit an sich ist nicht das wesentliche Kriterium eines Plugins. Wenn eine Komponente nicht weggelassen werden kann, ist sie kein Plugin.

Trotzdem solltest du deinen Entwurf so gestalten, daß sich die Oberfläche problemlos austauschen läßt. Ich verwende dazu gerne ein eigenes Modul, das sich um die benötigte, von der Oberfläche unabhängige Funktionalität kümmert: Plugins einbinden, Logging konfigurieren und solchen Kram. Auch die Schnittstellen für die tieferliegenden Funktionen sollten in der einen oder anderen Form in diesem Modul liegen, damit eine Oberfläche dann nur noch dieses Hauptmodul importieren muß.

Schwierig wird es dann, wenn die Plugins eigene Oberflächen mitbringen, die sich ja nach Möglichkeit nahtlos in die Hauptoberfläche integrieren sollen. Spätestens dann wird es schwierig, die Oberfläche einfach so auszutauschen. Eine richtig befriedigende Lösung habe ich an der Stelle auch noch nicht gefunden, aber es hilft, die Plugins an sich ähnlich zu organisieren wie das Hauptprogramm. Trotzdem müssen dann alle Plugins mit Oberfläche angefasst werden, wenn du umsteigen oder mehrgleisig fahren willst.

Edit: Tippfehler beseitigt und einen Satz etwas klarer formuliert
BlackJack

@Pekh: Ich denke Dein Plugin-Begriff ist zu streng. Mal am Beispiel Audioplayer: Dekodieren von Formaten kann man IMHO per Plugin lösen. Wenn alle Formate mit Plugins dekodiert werden, ist der Player ohne Plugins nutzlos und nach Deiner Definition wären es damit keine Plugins mehr, weil man nicht alle weglassen kann.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Hallo!

Danke für eure Antworten. Was das Weglassen der essentiellen Plugins betrifft: Natürlich sollen die auch irgendwie "ersetzbar" sein - z.B. wenn ein anderes Toolkit gewünscht wird. Allerdings sollen sie nicht zu Laufzeit ein- und abschaltbar sein, wie es bei den anderen Plugins der Fall wäre.

Mich interessierte vor allem, ob ihr der Meinung seid, ob ein solcher "mirco-Ansatz", in dem das eigentliche Programm vielleicht nur 300 Zeilen groß ist und alle anderen Funktionen recht dynamsich nachlädt, performant und sinnvoll sein könnte.
Was die "Schnittstellen für tieferliegende[n] Funktionen" angeht: Dies würde meiner Vorstellung nach eben das Pluginsystem selbst sein: Wenn ich also mit meinem Plugin X einen Knopf auf einer Toolbar des Hauptfensters hinzufügen möchte, würde das etwa wie folgt aussehen:

Code: Alles auswählen

### Nur zur Anschauung
window = self.plugin_interface.get_class("main_window")
window.toolbar.insert_item(-1, gtk.Button("Test))
Das Plugin System würde dabei die geladenen Plugins durchlaufen und die entsprechende Klasse zurück geben. Die Integrität würde durch das System selbst gewährleistet, da die Windows-Klasse in meinem Beispiel essentiell wäre und das Programm abbrechen würde, wenn die Klasse nicht vorhanden wäre.

Naja, vielleicht werde ich bei Gelegenheit mein bestehendes Projekt auf diesen Ansatz portieren - ich stelle mir das recht praktisch vor.

lG

brb
Antworten