web-dev-qa-db-de.com

Plugin-Architektur in Web-Apps (Beispiele oder Code-Snippets?)

Ich versuche zu lernen, eine Webanwendung zu entwickeln (vorzugsweise NodeJS/MongoDB, obwohl ich zuvor PHP und Python verwendet habe), die über Plugins hochgradig erweiterbar und anpassbar ist, um deaktivierte Funktionen zu aktivieren. 

Eine mögliche Option ist die Verwendung von Wordpress mit Hooks für Plugins und Widgets zum Einhängen, jedoch fehlt die richtige Trennung von Ansicht und Logikcode. Das bleibt eine Möglichkeit, von der man lernen kann. Gibt es noch andere Möglichkeiten? 

Haben Sie Code-Ausschnitte oder Beispielanwendungen, von denen ich lernen kann? Sprache oder Rahmenbedingungen sind nicht so wichtig, ich könnte das Konzept dahinter wohl grob ausmachen

34
Jiew Meng

Eine gute Plugin-Architektur ist von Grund auf schwierig zu erreichen, bietet aber ihre eigenen Belohnungen. Es macht die Software flexibel und einfach zu warten, indem die Komplexität lokalisiert wird. Die wichtigste Fähigkeit, die es erfordert, ist die Fähigkeit, lose gekoppelten Code zu schreiben. Dies erfordert ein sehr sicheres Verständnis des Polymorphismus, Demeters Gesetz und des damit verbundenen Hollywood-Prinzips .

Ich empfehle Ihnen, sich zunächst mit diesen, dann mit den folgenden Entwurfsmustern vertraut zu machen, wodurch sich die Schwierigkeit erheblich verringert:

  • Command Pattern : Gibt Plug-in-Modulen einen konsistenten Einstiegspunkt, sodass sie problemlos ein- und ausgelagert werden können. Web-basiertes Beispiel von IBM .
  • Memento : Erfassen, Halten und Auslagern des Status ohne Verletzung der Kapselung. Plugins können vom Container konfiguriert werden.
  • Rückruf : Ermöglicht den Plugin-Modulen den Zugriff auf "Dienste" aus dem Container/der Umgebung.
  • Dependency Injection : Eine Möglichkeit, die Kopplung von Plugin-Modulen von ihrer Umgebung zu lösen.
  • Abstract Factory Pattern : Installation und Instanziierung des Plugins in der Umgebung.
  • Builder Pattern : Erforderlich für alle nicht trivialen Plugin-Architekturen, bei denen Plugin-Module voneinander abhängig sind.

Wenn Sie diese verstanden haben, schauen Sie sich einige der vorhandenen Plugin Framework-Implementierungen und -Architekturen an, um zu sehen, wie sie verwendet wurden. Apache hat mehrere in Struts , Geronimo Custom Server Assemblys und Tomcat JNDI Resources ; Auch das Eclipse Plugin Framework .

72
Martin Spamer

Wir haben keine Plugin-Architektur als solche, aber ich erkläre Ihnen, wie wir unseren Client-Code locker miteinander verbinden, und vielleicht gibt Ihnen das ein paar Ideen.

Wir benutzen asp.net. Wir liefern eine main.aspx-Seite, die zunächst eine JavaScript-Datei für Vermittler enthält. Es definiert ein globales Objekt - nennen Sie es Vermittler - das einzige globale Objekt, das wir definieren. 

Der Mediator bietet eine einfache Schnittstelle für das Veröffentlichen und Abonnieren von Nachrichten:

mediator.subscribe(messageName, callback);
mediator.publish(messageName);

Nach der Datei mediator.js enthält die Hauptseite eine Reihe weiterer JavaScript-Dateien, von denen jede aus einer unmittelbaren Funktion besteht, die ihre Funktionalität beim Mediator ..__ registriert. Mehr über dieses Muster finden Sie hier , oder eine vorherige Frage von mir hier .

Sie könnten einen ähnlichen Ansatz verfolgen: Definieren Sie ein einzelnes globales Objekt (etwa pluginFramework), das eine Schnittstelle für Plugins bietet, um deren Funktionalität zu registrieren. Wenn Sie die HTML-Seite für die Bereitstellung an den Client erstellen, schließen Sie zunächst die pluginFramework-Datei und dann dynamisch die gewünschten JavaScript-Plugin-Dateien ein, die vom Benutzer oder vom Gerät abhängen können (z. B. verschiedene Plugins, wenn das Gerät durch Berühren aktiviert wird?). Diese Plugin-Dateien würden ihre Funktionalität mit einer Sofortfunktion zum PluginFramework hinzufügen.

Hier ein Beispiel, wie Plugins das Hinzufügen von Funktionen zu einem Menü in der Benutzeroberfläche ermöglichen:

pluginFramework.js:

var pluginFramework = (function() {
    var menuItems = [];
    function addMenuItemPrivate(itemName, callback) {
        // e.g. add itemName and callback to menuItems
    }
    return {
        addMenuItem: addMenuItemPrivate;
    }
})());

photoPlugin.js:

(function() {
    function addPhoto() {
        //...
    }
    pluginFramework.addMenuItem('add photo', addPhoto)
})());

Hoffe das war irgendwie hilfreich!

5
GarethOwen

Aus Ihrem Kommentar geht hervor, dass Sie eine Multi-Tenant-Architektur erstellen.

Dies ist eine komplexe Anforderung, die normalerweise nur schwer nachzurüsten ist. Es hängt weitgehend davon ab, wo Sie anfangen. 

Erstens müssen Sie zunächst eine anständig faktorisierte Webanwendung haben. Wenn Sie ein MVC-Framework verwenden, haben Sie einen Ausgangspunkt. 

Zweitens müssen Sie entscheiden, wo Sie Erweiterungen unterstützen werden. Kann ein Client für Instace eine vollständig separate Skin für seine Benutzeroberfläche haben? Wenn ja, brauchen Sie ein Skinning-Framework. Können Clients alles ändern oder einfach verschiedene Komponenten an Schlüsselpunkten einbinden (z. B. ein benutzerdefinierter Zahlungsanbieter oder ein benutzerdefiniertes Authentifizierungsschema). Es ist viel einfacher, eine begrenzte Anzahl von Erweiterungspunkten zu unterstützen, als ein Framework zu entwerfen, mit dem alles erweitert werden kann. 

Als nächstes Ihre Datenstrategie; dort ein guter Artikel zum Thema Multi Tenancy auf MSDN ; Es ist auf relationale Datenbanken ausgerichtet, bietet jedoch Ideen, die Sie bei Mongo anwenden können.

Schließlich müssen Sie eine Komponentenarchitektur entwickeln, die die benötigten Erweiterungspunkte unterstützt. Wenn Sie mit einer Webanwendung arbeiten, müssen Sie Modell, Ansicht, Controller und Dauerhaftigkeit ändern können. Die beste Lösung besteht darin, die Art und Weise zu verwenden, in der Ihr MVC-Framework arbeiten möchte, und die Logik "für Mandant x, do y; für Tenant z, do w" in die Controller-Schicht zu setzen. Spielen Sie damit, lassen Sie es in einigen Fällen funktionieren, die Sie brauchen, und ermitteln Sie dann, was daran falsch ist, und beheben Sie es. 

4
Neville Kuyt

Wenn Sie selbst die Kundenanpassung vornehmen, klingt Django dafür ideal. Erstellen Sie Ihre Kernanwendung, die alle grundlegenden Funktionen behandelt, die Sie möchten. Dann müssen Sie für jedes logisch getrennte Element eine neue App erstellen/plugin erstellen, die Sie in Ihre Hauptapplikation einfügen können, indem Sie diese App einfach zu Ihren installierten Apps in den Einstellungen hinzufügen. 

Dies erledigt das Skinning (einfach in eine neue Vorlage base_site.html ploppen, alle anderen davon übernehmen), Unterstützung für mehrere Datenbanken, Plugins und gibt Ihnen die Möglichkeit, neue Plugins/Funktionen schnell zu entwickeln und zu implementieren.

Unter merengue oder pinax finden Sie allgemeine Beispiele für Ihr internes System.

0
Murph