How To Create a Flexible Plug-In Architecture?

This is not an answer as much as a bunch of potentially useful remarks/examples.

  • One effective way to make your application extensible is to expose its internals as a scripting language and write all the top level stuff in that language. This makes it quite modifiable and practically future proof (if your primitives are well chosen and implemented). A success story of this kind of thing is Emacs. I prefer this to the eclipse style plugin system because if I want to extend functionality, I don't have to learn the API and write/compile a separate plugin. I can write a 3 line snippet in the current buffer itself, evaluate it and use it. Very smooth learning curve and very pleasing results.

  • One application which I've extended a little is Trac. It has a component architecture which in this situation means that tasks are delegated to modules that advertise extension points. You can then implement other components which would fit into these points and change the flow. It's a little like Kalkie's suggestion above.

  • Another one that's good is py.test. It follows the "best API is no API" philosophy and relies purely on hooks being called at every level. You can override these hooks in files/functions named according to a convention and alter the behaviour. You can see the list of plugins on the site to see how quickly/easily they can be implemented.

A few general points.

  • Try to keep your non-extensible/non-user-modifiable core as small as possible. Delegate everything you can to a higher layer so that the extensibility increases. Less stuff to correct in the core then in case of bad choices.
  • Related to the above point is that you shouldn't make too many decisions about the direction of your project at the outset. Implement the smallest needed subset and then start writing plugins.
  • If you are embedding a scripting language, make sure it's a full one in which you can write general programs and not a toy language just for your application.
  • Reduce boilerplate as much as you can. Don't bother with subclassing, complex APIs, plugin registration and stuff like that. Try to keep it simple so that it's easy and not just possible to extend. This will let your plugin API be used more and will encourage end users to write plugins. Not just plugin developers. py.test does this well. Eclipse as far as I know, does not.

One of the best plug-in architectures that I have seen is implemented in Eclipse. Instead of having an application with a plug-in model, everything is a plug-in. The base application itself is the plug-in framework.

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html


In my experience I've found there are really two types of plug-in Architectures.

  1. One follows the Eclipse model which is meant to allow for freedom and is open-ended.
  2. The other usually requires plugins to follow a narrow API because the plugin will fill a specific function.

To state this in a different way, one allows plugins to access your application while the other allows your application to access plugins.

The distinction is subtle, and sometimes there is no distiction... you want both for your application.

I do not have a ton of experience with Eclipse/Opening up your App to plugins model (the article in Kalkie's post is great). I've read a bit on the way eclipse does things, but nothing more than that.

Yegge's properties blog talks a bit about how the use of the properties pattern allows for plugins and extensibility.

Most of the work I've done has used a plugin architecture to allow my app to access plugins, things like time/display/map data, etc.

Years ago I would create factories, plugin managers and config files to manage all of it and let me determine which plugin to use at runtime.

  • Now I usually just have a DI framework do most of that work.

I still have to write adapters to use third party libraries, but they usually aren't that bad.