2012-05-26 10 views
25

Sto cercando di imparare a sviluppare un'applicazione Web (preferibilmente NodeJS/MongoDB, anche se ho usato PHP e Python in precedenza) che è altamente estensibile e personalizzabile tramite plugin per abilitare disabilitato funzionalità.Architettura plugin nelle app Web (esempi o frammenti di codice?)

Una possibile opzione consiste nell'utilizzare Wordpress con ganci per plug-in e widget da agganciare, ma senza una separazione adeguata tra vista e codice logico. Questa rimane un'opzione da cui imparare. Ci sono altre opzioni?

Avete snippet di codice o applicazione di esempio da cui posso imparare? La lingua o il framework non è così importante, probabilmente potrei approssimativamente capire il concetto di

+0

che tipo di funzionalità si desidera estendere con i plugin? Ho bisogno di qualche tipo di esempio per entrare in questo. – GarethOwen

+0

1 esempio è come in WordPress, potrei estendere la funzionalità tramite widget e ganci. Un altro esempio potrebbe essere Tumblr. Potrebbe esserci il post di testo di base, quindi più tipi di post come Foto, Codice ecc. –

+0

Chi prevedi di estendere? È una squadra interna, o c'è qualcuno su internet? L'app Web è molto specifica, ad es. un sistema di time card per freelance - o è generico, ad es. un sistema di gestione dei contenuti? –

risposta

47

Una buona architettura di plugin è difficile da ottenere da zero, ma offre i suoi vantaggi. Rende il software flessibile e semplice da gestire localizzando la complessità. L'abilità principale che richiede è la capacità di scrivere loosely coupled code. Ciò richiede una comprensione molto ferma del polimorfismo, Demeter's Law e il relativo Hollywood principle.

Vi consiglio inizialmente guadagna una buona dimestichezza con quelli, poi i seguenti modelli di progettazione, che ridurrà la difficile in modo significativo:

  • Command Pattern: Dà Plugin moduli A punto di ingresso costante, permettendo loro di essere facilmente scambiato dentro e fuori, un Web Based example from IBM.
  • Memento: cattura, trattieni ed esternalizza lo stato senza violare l'incapsulamento, consente ai plugin di essere configurati dal contenitore.
  • Call Back: consente ai moduli plug-in di accedere ai "servizi" dal contenitore/ambiente.
  • Dependency Injection: un modo per allentare l'accoppiamento di moduli plug-in dal loro ambiente.
  • Abstract Factory Pattern: installazione e creazione dell'istanza del plug-in nell'ambiente.
  • Builder Pattern: necessario per qualsiasi architettura di plugin non banale in cui i moduli plug-in dipendono l'uno dall'altro.

Una volta afferrati, studia alcune delle implementazioni e architetture di Plugin Framework esistenti per vedere come sono stati utilizzati. Apache ne ha diversi in Struts, Geronimo custom server assemblies e Tomcat JNDI Resources; Anche lo Eclipse plugin framework.

4

Non abbiamo un'architettura di plugin in quanto tale, ma spiegherò come stiamo mantenendo il nostro codice client liberamente accoppiato, e forse ti darò alcune idee

Stiamo usando asp.net. Forniamo una pagina main.aspx che include per prima cosa un file javascript mediatore. Definisce un oggetto globale - chiamalo mediatore - che è l'unico oggetto globale che definiamo.

Il mediatore espone una semplice interfaccia con publish and subscribe messaggi:

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

Dopo che il file mediator.js, la pagina principale comprende un certo numero di altri file JavaScript, ognuno dei quali è costituito da una funzione immediata che registra la sua funzionalità con il mediatore. È possibile trovare ulteriori informazioni su questo modello here o vedere una domanda precedente. here.

È possibile seguire un approccio simile: definire un singolo oggetto globale (ad esempio pluginFramework) che offra un'interfaccia per i plug-in per registrare le loro funzionalità. Quando si crea la pagina html da consegnare al client, includere prima il file pluginFramework e quindi includere dinamicamente i file di plug-in JavaScript desiderati, che potrebbero dipendere dall'utente o dal dispositivo (ad esempio plug-in diversi se il dispositivo è abilitato al tocco?). Questi file plugin aggiungerebbero la loro funzionalità a pluginFramework con una funzione immediata.

Ecco un esempio di come consentire i plugin per aggiungere funzionalità a un menu nell'interfaccia utente:

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) 
})()); 

Speranza questo era in qualche modo utile!

3

Il tuo commento suggerisce che quello che stai creando è un multi-tenant architecture.

Questo è un requisito complesso - e di solito è piuttosto difficile adattarsi al retro; dipende in gran parte da dove stai iniziando.

In primo luogo, è necessario disporre di un'applicazione web con factoring decentemente in primo luogo; se stai usando un framework MVC, hai un punto di partenza.

In secondo luogo, è necessario decidere dove supportare le estensioni; per instace, può un cliente avere una skin completamente separata per l'interfaccia utente? Se è così, hai bisogno di una struttura skinning. I clienti possono cambiare tutto o semplicemente collegare diversi componenti nei punti chiave (ad esempio un fornitore di pagamenti personalizzato o uno schema di autenticazione personalizzato). È molto più semplice supportare un numero limitato di punti di estensione rispetto alla progettazione di un framework che consente di estendere qualsiasi cosa.

Successivamente, la strategia dei dati; c'è un good article on multi tenancy on MSDN; è orientato ai database relazionali, ma fornisce idee che puoi applicare a Mongo.

Infine, è necessario creare un'architettura componente che supporti i punti di estensione necessari. Poiché hai a che fare con un'applicazione web, devi essere in grado di modificare Modello, Visualizza, Controller e persistenza; la soluzione migliore è utilizzare il modo in cui il framework MVC vuole funzionare e inserire la logica "for tenant x, do y; tenant z, do w" nel livello controller. Gioca con questo, fallo funzionare per alcuni dei casi che ti servono, e poi scopri cosa c'è che non va e risolvilo.

0

Se si sta eseguendo la personalizzazione del client, Django sembra ideale per questo. Crea la tua applicazione principale che gestisce tutte le funzionalità di base che desideri. Quindi per ogni cosa logicamente separata che devi fare/plugin crea una nuova app che puoi collegare a quella principale, semplicemente aggiungendo l'app alle tue app installate nelle impostazioni.

Questo gestisce lo skinning (basta plopare in un nuovo modello base_site.html, ereditare tutti gli altri da esso), il supporto di più database, i plug-in e offre la possibilità di sviluppare e distribuire rapidamente nuovi plug-in/funzionalità.

Vedere merengue o pinax per ulteriori esempi generici di ciò che potrebbe essere il proprio sistema interno.