Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Anwendungsarchitektur

Plugin Architecture

Funktionen über angemeldete Plugins erweitern

Die Idee und ihr Nutzen

Die Schadenanwendung einer Versicherung kann Schadenberichte als Datei exportieren. Welche Dateiformate sie anbietet, steht nicht im Programmcode der Schadenanwendung. Jedes Format kommt aus einem Plugin, einem Zusatzbaustein, der sich getrennt von der Anwendung installieren lässt. Eine Tochtergesellschaft braucht Berichte im Format CSV, einer Tabelle als reiner Textdatei, in der jede Zeile einen Schaden enthält und Kommas die Spalten trennen, um die Berichte in ihre eigene Auswertung zu übernehmen. Die Tochtergesellschaft installiert dafür ein CSV-Plugin. Ab dann bietet die Schadenanwendung bei der Tochtergesellschaft auch den CSV-Export an, ohne dass jemand den Programmcode der Schadenanwendung ändern musste. Diese Bauweise heißt Plugin Architecture, auf Deutsch Plugin-Architektur.

Bausteine: Sachbearbeiterin: will einen Bericht exportieren; Schadenanwendung: bietet den Erweiterungspunkt „Export“; CSV-Plugin: von der Tochtergesellschaft installiert; PDF-Plugin: weitere mögliche Erweiterung. Verbindungen: Sachbearbeiterin — Schadenanwendung; Schadenanwendung — CSV-Plugin; Schadenanwendung — PDF-Plugin. Die Schadenanwendung bietet einen Erweiterungspunkt „Export“; jedes Dateiformat kommt aus einem eigenen, angemeldeten Plugin.

Wie funktioniert es?

Jede Gesellschaft der Versicherung betreibt eine eigene Installation derselben Schadenanwendung. Alle Installationen haben denselben Programmcode und unterscheiden sich nur darin, welche Plugins im Plugin-Verzeichnis der jeweiligen Installation angemeldet sind. Das Plugin-Verzeichnis ist eine Liste der Plugins, die in dieser Installation installiert und freigegeben sind. Die Tochtergesellschaft installiert das CSV-Plugin und meldet es dabei im Plugin-Verzeichnis ihrer Installation an. Freigegeben ist ein Plugin, wenn die Tochtergesellschaft es geprüft und für ihre Sachbearbeiter zugelassen hat. Danach öffnet eine Sachbearbeiterin der Tochtergesellschaft in der Schadenanwendung die Exportfunktion. Die Schadenanwendung fragt das Plugin-Verzeichnis, welche Formate freigegeben sind, und erhält CSV als verfügbares Format zurück. Die Schadenanwendung bietet der Sachbearbeiterin CSV zur Auswahl an, und die Sachbearbeiterin wählt CSV. Die Schadenanwendung lädt das CSV-Plugin und übergibt ihm den Schadenbericht. Das CSV-Plugin erzeugt die CSV-Datei und gibt sie an die Schadenanwendung zurück. Ein PDF-Plugin ließe sich später auf dieselbe Weise im Plugin-Verzeichnis anmelden. Andere Gesellschaften haben das CSV-Plugin nicht installiert und sehen den CSV-Export nicht.

Das Team der Schadenanwendung legt fest, für welche Aufgaben die Schadenanwendung Plugins aufruft, hier für das Erzeugen einer Exportdatei. Eine solche Aufgabe heißt Erweiterungspunkt, hier der Erweiterungspunkt „Export“. Für den Erweiterungspunkt beschreibt das Team der Schadenanwendung eine Schnittstelle, also eine verbindliche Vereinbarung über Eingaben und Ergebnis: Ein Exportplugin erhält einen Schadenbericht mit festgelegten Feldern und liefert daraus eine Datei. Das CSV-Plugin bietet diese Schnittstelle an, und die Schadenanwendung ruft sie auf. Ein Plugin ist ein eigenes Paket und wird von einem Team geschrieben, das nicht das Team der Schadenanwendung sein muss. Je nachdem, wie die Schadenanwendung gebaut ist, lädt sie ein Plugin schon beim Start oder erst, wenn es gebraucht wird. Plugins werden oft unabhängig von der Schadenanwendung entwickelt, mit eigenen Versionsnummern versehen und verteilt. Jedes Plugin sollte deshalb angeben, für welche Version der Schnittstelle es geschrieben wurde, und die Schadenanwendung sollte das Plugin nur laden, wenn diese Version zur installierten Schadenanwendung passt. Sonst könnte ein altes Plugin nach einer Änderung der Schnittstelle abstürzen oder falsche Dateien erzeugen.

Meldet das CSV-Plugin beim Erzeugen der Datei einen Fehler, muss die Schadenanwendung den Fehler abfangen und der Sachbearbeiterin anzeigen, dass der Export gescheitert ist. Die Plugin-Architektur allein stellt nicht sicher, dass ein Plugin richtig arbeitet oder vertrauenswürdig ist. Ob ein Plugin nur die übergebenen Daten sieht oder auf alle Daten der Schadenanwendung zugreifen kann, hängt davon ab, wie die Schadenanwendung das Plugin lädt und abschottet. Startet die Schadenanwendung das Plugin zum Beispiel als eigenes Programm und gibt ihm nur den Schadenbericht, kann das Plugin keine anderen Schadendaten lesen.

Plugin-Architektur: die Tochtergesellschaft ergänzt einen CSV-Export

Beteiligte: Installation: der Tochtergesellschaft; Plugin-Verzeichnis: führt installierte und freigegebene Plugins; Sachbearbeiterin: will einen Bericht exportieren; Schadenanwendung: bietet den Erweiterungspunkt „Export“; CSV-Plugin: setzt die Export-Schnittstelle um; PDF-Plugin: weitere mögliche Erweiterung. Ablauf: 1. Die Tochtergesellschaft installiert das CSV-Plugin und meldet es im Plugin-Verzeichnis ihrer Installation an. 2. Eine Sachbearbeiterin der Tochtergesellschaft öffnet in der Schadenanwendung die Exportfunktion. 3. Die Schadenanwendung fragt das Plugin-Verzeichnis, welche Formate freigegeben sind. 4. Das Plugin-Verzeichnis meldet CSV als verfügbares Format. 5. Die Schadenanwendung bietet CSV zur Auswahl an. 6. Die Sachbearbeiterin wählt CSV. 7. Die Schadenanwendung lädt das CSV-Plugin und übergibt ihm den Schadenbericht. 8. Das CSV-Plugin erzeugt die CSV-Datei und gibt sie an die Schadenanwendung zurück. Die Schadenanwendung musste dafür nicht geändert werden. 9. Ein PDF-Plugin ließe sich später auf dieselbe Weise im Plugin-Verzeichnis anmelden. Gesellschaften ohne CSV-Plugin sehen den CSV-Export nicht.

Wann ist es sinnvoll und wann nicht?

Eine Plugin-Architektur lohnt sich

  • Kunden, Partner oder andere Teams sollen ein Produkt selbst erweitern, dürfen aber den Programmcode des Produkts nicht ändern. Bei der Versicherung ist die Schadenanwendung das Produkt. Die Gesellschaften haben eigene Entwickler, die nicht in den Programmcode der Schadenanwendung eingreifen dürfen. Mit einem Plugin können diese Entwickler eine Ergänzung wie den CSV-Export trotzdem selbst schreiben.
  • Viele Nutzer haben unterschiedliche Wünsche, die das Team eines Produkts nicht alle vorhersehen kann. Bei der Versicherung braucht die eine Gesellschaft einen CSV-Export, die andere eine Anbindung an ein bestimmtes Archiv, die dritte eine eigene Prüfung für Kfz-Schäden. Muss das Team der Schadenanwendung für jeden Wunsch den Programmcode ändern, testen und eine neue Version an alle ausliefern, wird es zum Engpass. Das Team der Schadenanwendung liefert neue Versionen ohnehin nur in größeren Abständen aus, und die Gesellschaften warten Monate auf kleine Ergänzungen. Mit Plugins schreibt jede Gesellschaft ihre Ergänzung selbst und installiert sie, wann sie will.
  • Verschiedene Installationen derselben Anwendung brauchen unterschiedliche Zusammenstellungen von Funktionen. Ohne Plugins erhalten alle Gesellschaften Funktionen, die nur eine einzige braucht. Mit Plugins installiert jede Gesellschaft nur die Plugins, die sie braucht.
  • Ein Werkzeug hat viele wahlweise Funktionen, von denen jeder Nutzer nur einen Teil braucht. Beispiele sind Entwicklungsumgebungen, Webbrowser und Automatisierungsserver. Ohne Plugins müsste jede Installation des Werkzeugs alle Funktionen enthalten. Mit Plugins wählt jeder Nutzer die Funktionen aus, die er braucht.

Eine Plugin-Architektur ist nicht das Richtige

  • Alle Funktionen kommen ohnehin vom Team der Schadenanwendung und werden immer gemeinsam ausgeliefert. Niemand sonst schreibt dann Erweiterungen, und alle Gesellschaften erhalten dieselben Funktionen. Dann gliedert das Team der Schadenanwendung den Code in Module, also abgegrenzte Teile des eigenen Programmcodes, und liefert neue Exportformate mit der nächsten Version aus. Erweiterungspunkte, Plugin-Verzeichnis und Versionsprüfung muss das Team der Schadenanwendung dann nicht bauen und pflegen.
  • Die gewünschten Erweiterungen brauchen Zugriff auf viele interne Abläufe der Anwendung. Ein Beispiel ist eine Erweiterung, die die Reihenfolge der Bearbeitungsschritte eines Schadens ändern soll. Dann lässt sich keine kleine, dauerhaft gleichbleibende Schnittstelle beschreiben, und ein Erweiterungspunkt müsste bei jeder Version der Anwendung geändert werden. Stattdessen baut das Team der Schadenanwendung diese Erweiterungen selbst in den Programmcode ein. So muss es keine Schnittstelle pflegen, deren Änderungen bei jeder Version die Plugins anderer Teams unbrauchbar machen.
  • Plugins sollen aus fremden Quellen kommen, aber es gibt weder eine Prüfung vor der Freigabe noch eine Möglichkeit, die Plugins von den Daten der Anwendung abzuschotten. Dann baut das Team der Schadenanwendung die gewünschten Funktionen selbst ein, oder die Versicherung lässt nur Plugins zu, die ihre eigenen Entwickler geschrieben haben. So führt die Schadenanwendung keinen ungeprüften fremden Programmcode aus, der auf alle Schadendaten zugreifen könnte.
  • Die gewünschten Funktionen sind schon eingebaut und sollen nur je Gesellschaft ein- oder ausgeschaltet werden. Plugins würden dann nur Funktionen nachliefern, die schon im Programmcode der Schadenanwendung stehen. Stattdessen schaltet jede Gesellschaft die eingebauten Funktionen mit Feature Toggles ein oder aus, also mit Schaltern in den Einstellungen ihrer Installation. Niemand muss dafür Plugins schreiben, installieren und freigeben.
  • Fast die gesamte fachliche Funktion soll aus austauschbaren Bausteinen bestehen, und das Grundprogramm soll nur noch Laden und Aufrufen übernehmen. Die Plugin-Architektur geht dagegen von einer vollständigen Schadenanwendung aus, die nur an einzelnen Erweiterungspunkten wie „Export“ Plugins aufruft. Dann baut das Team der Schadenanwendung die Anwendung als Microkernel Architecture: Ein kleines Grundprogramm lädt die Bausteine und ruft sie auf, und auch die fachlichen Grundfunktionen kommen als Bausteine hinzu.

Nachteile und typische Fehler

Die Schnittstelle des Erweiterungspunkts wird zur Vereinbarung mit allen Plugin-Entwicklern. Jede Änderung daran kann bestehende Plugins unbrauchbar machen, deshalb lässt sich die Schnittstelle nur schwer ändern. Das Team der Schadenanwendung muss Erweiterungspunkte, Plugin-Verzeichnis und Versionsprüfung bauen, beschreiben und pflegen. Viele Plugins in unterschiedlichen Versionen machen Tests und Fehlersuche aufwendig, weil jede Installation eine andere Zusammenstellung haben kann. Plugins aus fremden Quellen müssen vor der Freigabe geprüft werden, weil sie eigenen Programmcode in der Schadenanwendung ausführen. Lädt die Schadenanwendung Plugins nur beim Start, muss sie nach der Installation eines Plugins neu gestartet werden, damit sie das neue Plugin erkennt.

Typische Fehler und woran man sie erkennt:

  • Absturz durch ein Plugin: Ein fehlerhaftes Plugin bringt die ganze Schadenanwendung zum Absturz, weil es im selben laufenden Programm ausgeführt wird wie die Schadenanwendung. Ein Beispiel ist ein Speicherüberlauf im Plugin. Erkennbar ist das an Abstürzen, die nur in Installationen mit einem bestimmten Plugin auftreten.
  • Unsicheres Plugin: Ein Plugin aus fremder Quelle führt eigenen Programmcode aus und greift dabei auf Schadendaten zu, die es nicht braucht. Erkennbar ist das, wenn überhaupt, an unerwarteten Datenzugriffen oder Netzverbindungen aus der Schadenanwendung heraus.
  • Unpassende Version: Das Team der Schadenanwendung ändert mit einem Update die Felder des Schadenberichts, den der Erweiterungspunkt „Export“ an die Plugins übergibt. Die Schadenanwendung prüft die Version der Schnittstelle nicht und lädt das alte CSV-Plugin trotzdem. Das alte CSV-Plugin findet die erwarteten Felder nicht und stürzt ab oder erzeugt Dateien mit fehlenden Spalten. Erkennbar ist das an Fehlern nach einem Update der Schadenanwendung, obwohl das Plugin unverändert ist.
  • Nicht nachstellbare Fehler: Jede Gesellschaft hat eine andere Zusammenstellung von Plugins in unterschiedlichen Versionen. Ein gemeldeter Fehler tritt beim Team der Schadenanwendung nicht auf. Erkennbar ist das an Fehlermeldungen, die sich nur in einer bestimmten Installation nachstellen lassen.

Weiterführend

Verwandte Ansätze

  • Inversion of Control: beschreibt das allgemeine Prinzip dahinter, dass die Anwendung die Plugins aufruft und nicht die Plugins die Anwendung.
  • Dependency Injection: ein Verfahren, mit dem die Anwendung ihren Plugins benötigte Dienste übergibt. Ein Beispiel ist der Zugriff auf Schadendaten.

Werkzeuge und Umsetzungen

  • PF4J: Java-Bibliothek für Plugins mit Erweiterungspunkten und Ladeverwaltung.
  • pluggy: Python-Bibliothek für Plugins; unter anderem das Testwerkzeug pytest baut darauf auf.
  • Jenkins: Automatisierungsserver, dessen Funktionsumfang zum großen Teil aus Plugins besteht.
  • Eclipse Equinox: Grundlage der Entwicklungsumgebung Eclipse, in der fast jede Funktion als Plugin eingebunden ist.

Quellen