Cooperating plug-ins

Log-in or register.

Cooperating plug-ins

Everybody has heard about the famous plug-ins design pattern. Allowing third-party extensions to one’s software was a key feature that took applications like Photoshop or Mozilla where they are today. But let's not stop there. With a few minor improvements, this design pattern can be much more useful - I call it Cooperating plug-ins.

An example

RealWorld Designer defines an interface for operation plug-ins (for example image filter). The operation has two core methods:

  • Create default configuration object.
  • Execute the operation.

The use scenario is simple:

  1. Create default configuration object.
  2. Alter the configuration to fit your needs.
  3. Execute the operation on given document with given configuration.

Standard plug-ins:

interface IPlugIn
{
    IConfigObject CreateConfig();
    bool Execute(IDocument doc, IConfigObject cfg);
}

There is of course a plug-in manager that has knows about all the plug-ins and can return the list of plug-in IDs and perform the actions on plug-in identified by an ID. If you take a look at the manager, it is very similar to the plug-in. It is able to create a default configuration by aggregating the default configuration of all plug-ins and a switch item. Ant it would be able to execute that operation.

interface IPlugInManager
{
    IDCollection EnumPlugInIDs();
    IConfigObject CreateConfig(IDType id);
    bool Execute(IDType id, IDocument doc, IConfigObject cfg);
}

Cooperating plug-ins:

interface ICoopPlugIn
{
    IConfigObject CreateConfig(IPlugInManager manager);
    bool Execute(IPlugInManager manager, IDocument doc, IConfigObject cfg);
}

This little change allows us to use one plug-in from another plug-in and create "meta-plug-ins". Meta-plug-ins can do a lot of unexpected stuff:

  • A plug-in that runs two other plug-ins in sequence. By nesting it, the number of plug-ins executed in one step is unlimited.
  • A plug-in that show the configuration dialog of a nested plug-in before it is executed.
  • A plug-in that runs the nested plug-in in another thread.

Yet another step

The manager can be modified in similar fashion:

interface ICoopPlugInManager
{
    IDCollection EnumPlugInIDs();
    IConfigObject CreateConfig(ICoopPlugInManager manager, IDType id);
    bool Execute(ICoopPlugInManager manager, IDType id, IDocument doc, IConfigObject cfg);
}

You may ask yourself what’s the point of having the extra argument in the methods, especially since it has the same type as the interface. It allows us to pass a different implementation of the manager to the actual plug-ins and customize the entire use scenario. In RealWorld Designer, there is a special manager that allows opening document in new windows.

Summary

Designing plug-in interfaces with cooperation in mind does not cost a lot and has the benefit of moving a lot of functionality out of the core of the application thus keeping it simple. If this is not reason enough for you, then just go away and return when you are ready ;-).

Recent comments

user icon Anonymous on March 7th 2016

How do I print with Real World Paint app?

user icon Anonymous
I wish there were...
What about ICL files?