web-dev-qa-db-fra.com

Architecture de plug-in dans les applications Web (exemples ou extraits de code?)

J'essaie d'apprendre à développer une application Web (de préférence NodeJS/MongoDB, bien que j'aie utilisé PHP et Python auparavant) qui soit hautement extensible et personnalisable via des plugins pour activer les fonctionnalités désactivées. 

Une option possible consiste à utiliser Wordpress avec des points d'ancrage pour les plug-ins et les widgets, mais il manque une séparation appropriée entre la vue et le code logique. Cela reste à être une option à apprendre. Il y a-t-il des alternatives? 

Avez-vous des extraits de code ou un exemple d'application dont je peux apprendre? Le langage ou le cadre n’est pas si important, je pourrais probablement expliquer le concept

34
Jiew Meng

Une bonne architecture de plugin est difficile à obtenir à partir de zéro, mais offre ses propres récompenses. Cela rend le logiciel flexible et simple à maintenir en localisant la complexité. La compétence la plus importante dont elle a besoin est la capacité d'écrire code faiblement couplé . Cela exige une très bonne compréhension du polymorphisme, loi de Demeter et le principe connexe Hollywood .

Je vous recommande de vous familiariser d'abord avec ceux-ci, puis avec les modèles de conception suivants, qui réduiront considérablement les difficultés:

  • Commande Pattern : donne aux modules de plug-in un point d'entrée cohérent, leur permettant d'être facilement échangés, un exemple basé sur le Web, fourni par IBM .
  • Memento : capturer, conserver et externaliser l'état sans violer l'encapsulation, permet la configuration des plugins par le conteneur.
  • Call Back : Permet aux modules de plug-in d'accéder aux "services" à partir du conteneur/de l'environnement.
  • Injection de dépendance : Une façon de détacher le couplage des modules de plug-in de leur environnement.
  • Abstract Factory Pattern : Installation et instanciation du plugin dans l'environnement.
  • Motif de constructeur : Requis pour toute architecture de plugin non triviale où les modules de plugin dépendent les uns des autres.

Une fois que vous les avez compris, étudiez certaines des implémentations et architectures de Plugin Framework existantes pour voir comment elles ont été utilisées. Apache en possède plusieurs dans Struts , des assemblages de serveurs personnalisés Geronimo et des ressources JNDI Tomcat ; Egalement le framework de plugin Eclipse

68
Martin Spamer

Nous n'avons pas d'architecture de plugin en tant que telle, mais j'expliquerai comment nous gardons le code de notre client peu couplé, et cela vous donnera peut-être quelques idées.

Nous utilisons asp.net. Nous livrons une page main.aspx qui comprend d’abord un fichier javascript. Il définit un objet global - appelez-le médiateur - qui est le seul objet global que nous définissions. 

Le médiateur présente une interface simple avec des messages de publication et d’abonnement:

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

Après le fichier mediator.js, la page principale comprend un certain nombre d’autres fichiers javaScript, chacun consistant en une fonction immédiate qui enregistre sa fonctionnalité avec le médiateur . Vous trouverez plus d’informations sur ce modèle ici , ou voir une de mes questions précédentes ici .

Vous pouvez suivre une approche similaire: définissez un seul objet global (par exemple, pluginFramework) offrant une interface permettant aux plug-in d’enregistrer leurs fonctionnalités. Lorsque vous créez la page html à livrer au client, commencez par inclure le fichier pluginFramework, puis de manière dynamique, les fichiers de plug-in JavaScript souhaités, qui peuvent dépendre de l'utilisateur ou du périphérique (par exemple, des plug-ins différents si le périphérique est activé au toucher?). Ces fichiers de plug-in ajouteraient leurs fonctionnalités au pluginFramework avec une fonction immédiate.

Voici un exemple sur la façon d'autoriser les plug-ins à ajouter des fonctionnalités à un menu de l'interface utilisateur:

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

J'espère que c'était d'une certaine manière utile!

5
GarethOwen

Votre commentaire suggère que ce que vous construisez est une architecture multi-tenant .

Il s'agit d'une exigence complexe - et qui est généralement assez difficile à réajuster; cela dépend en grande partie de votre point de départ. 

Tout d'abord, vous devez avoir une application Web bien factorisée; Si vous utilisez un framework MVC, vous avez un point de départ. 

Deuxièmement, vous devez décider où vous allez prendre en charge les extensions. pour instace, un client peut-il avoir un skin séparé complet pour son interface utilisateur? Si c'est le cas, vous avez besoin d'un framework de skinning. Les clients peuvent-ils tout changer ou simplement connecter différents composants à des points clés (par exemple, un fournisseur de paiement personnalisé ou un schéma d'authentification personnalisé). Il est beaucoup plus facile de prendre en charge un ensemble limité de points d’extension que de concevoir un cadre permettant d’agrandir n’importe quel élément. 

Ensuite, votre stratégie de données; il y a un bon article sur la multi-location sur MSDN ; il est destiné aux bases de données relationnelles, mais fournit des idées que vous pouvez appliquer à Mongo.

Enfin, vous devez mettre au point une architecture de composant prenant en charge les points d’extension dont vous avez besoin. Lorsque vous traitez avec une application Web, vous devez pouvoir modifier le modèle, la vue, le contrôleur et la persistance. La meilleure solution consiste à utiliser la structure de votre infrastructure MVC et à placer la logique "pour le locataire x, do y; pour le locataire z, do w" dans la couche contrôleur. Jouez avec cela, faites en sorte que cela fonctionne dans certains des cas dont vous avez besoin, puis déterminez ce qui ne va pas et remédiez à la situation. 

4
Neville Kuyt

Si vous personnalisez vous-même le client, Django semble idéal pour cela. Créez votre application principale qui gère toutes les fonctionnalités de base que vous souhaitez. Ensuite, pour chaque élément séparé logiquement, vous devez créer/créer une nouvelle application que vous pouvez connecter à votre application principale, en ajoutant simplement cette application à vos applications installées dans les paramètres. 

Cela gère la skin (plop dans un nouveau modèle base_site.html, tous les autres en héritent), la prise en charge de plusieurs bases de données, des plugins et vous donne la possibilité de développer et de déployer rapidement de nouveaux plugins/fonctionnalités.

Voir merengue ou pinax pour des exemples plus génériques de ce que votre système interne pourrait être.

0
Murph