Plugin Architecture in Web Apps (Examples or Code Snippets?)

31,461

Solution 1

A good plugin architecture is difficult to achieve from scratch, but offers its own rewards. It makes the software flexible and simple to maintain by localising complexity. The foremost skill it requires is the ability to write loosely coupled code. This demands a very firm grasp of polymorphism, Demeter's Law and the related Hollywood principle.

I recommend that you initially gain a good familiarity with those, then the following design patterns, which will reduce the difficult significantly :

  • Command Pattern : Gives Plugin Modules a consistent entry point, allowing them to be readily swapped in and out, a Web Based example from IBM.
  • Memento : Capture, hold and externalise state without violating encapsulation, allows plugins to be configured by the container.
  • Call Back : Allows the Plugin Modules to access 'services' from the container/environment.
  • Dependency Injection : A way to loosen the coupling of Plugin Modules from their environment.
  • Abstract Factory Pattern : Installing and instantiating the Plugin in the environment.
  • Builder Pattern : Required for any non trivial plugin architecture where Plugin Modules are dependent on each other.

Once you grasp those, study some of the existing Plugin Framework implementations and architectures to see how they've been used. Apache have several in Struts, Geronimo custom server assemblies and Tomcat JNDI Resources; Also the Eclipse plugin framework.

Solution 2

We've not got a plugin architecture as such, but I'll explain how we are keeping our client code loosely coupled, and maybe it will give you some ideas.

We are using asp.net. We deliver a main.aspx page which first includes a mediator javascript file. It defines a global object - call it mediator - which is the only global object that we define.

The mediator exposes a simple interface with publish and subscribe messages:

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

After the mediator.js file, the main page includes a number of other javaScript files, each of which consists of an immediate function which registers it's functionality with the mediator. More about this pattern can be found here, or see a previous question of mine here.

You could follow a similar approach - define a single global object (say pluginFramework) which offers an interface for plugins to register their functionality. When you build the html page to deliver to the client, first include the pluginFramework file and then dynamically include the desired JavaScript plugin files, which could depend on the user or the device (e.g. different plugins if the device is touch enabled?). These plugin files would add their functionality to the pluginFramework with an immediate function.

Here is an example of how to allow plugins to add functionality to a menu in the UI:

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

Hope this was in some way helpful!

Solution 3

Your comment suggests that what you're building is a multi-tenant architecture.

This is a complex requirement - and one that's usually quite hard to retro-fit; it largely depends on where you're starting from.

Firstly, you need to have a decently factored web application in the first place; if you're using an MVC framework, you've got a starting point.

Secondly, you need to decide where you're going to support extensions; for instace, can a client have a complete separate skin for their UI? If so, you need a skinning framework. Can clients change everything, or just plug in different components at key points (e.g. a custom payment provider, or a custom authentication scheme). It's a lot easier to support a limited set of extension points than designing a framework that allows anything to be extended.

Next, your data strategy; there a good article on multi tenancy on MSDN; it's geared at relational databases, but provides ideas you can apply to Mongo.

Finally, you have to come up with a component architecture that supports the extension points you need. As you're dealing with a web application, you need to be able to modify Model, View, Controller and persistance; the best solution is to use the way your MVC framework wants to work, and put the "for tenant x, do y; for tenant z, do w" logic in the controller layer. Play with this, make it work for some of the cases you need, and then work out what's wrong about that and fix it.

Solution 4

If you yourself are doing the client customization, Django sounds ideal for this. Create your core application that handles all the basic functionality you would like. Then for each logically separated thing you need to do/plugin create a new app that you can plug into your main one, simply by adding that app to your installed apps in settings.

This handles skinning (just plop in a new base_site.html template, have all your others inherit from it), multiple database support, plugins, and gives you the ability to pretty quickly develop and deploy new plugins/features.

See merengue or pinax for more generic examples of what your internal system could be.

Share:
31,461
Jiew Meng
Author by

Jiew Meng

Web Developer & Computer Science Student Tools of Trade: PHP, Symfony MVC, Doctrine ORM, HTML, CSS, jQuery/JS Looking at Python/Google App Engine, C#/WPF/Entity Framework I hope to develop usable web applications like Wunderlist, SpringPad in the future

Updated on July 09, 2022

Comments

  • Jiew Meng
    Jiew Meng almost 2 years

    I am trying to learn to develop a web application (preferably NodeJS/MongoDB, although I used PHP and Python before) that is highly extensible and customizable via plugins to enable disabled functionality.

    One possible option is to use Wordpress with hooks for plugins and widgets to hook into, its however lacking proper separation of view and logic code. That remains to be one option to learn from. Are there any other options?

    Do you have any code snippets or example application I can learn from? Language or framework is not so important, I could probably roughly make out the concept behind

  • Admin
    Admin almost 6 years
    Solid list. Are stackable middleware a different pattern or has another name mentioned?
  • gaurav5430
    gaurav5430 about 2 years
    Is there a more detailed text somewhere or some helpful links which talk about the kind of things being talked about in this comment ?