Klaus Marquardt - PlugIns

Concepts

The idea of Plug-ins is to extend the behaviour and features of an application even after the application has been finished and shipped.
Plug-in concepts have been around before Eclipse, e.g. in many operating systems and IDE's. Dynamic loading of Plug-in components became convenient when mainstream operating systems supported dynamic loading of libraries, like the Windows DLLs.

Here is a simple example to start your own Plug-in loading mechanism.

Unlike other extensibility concepts, Plug-ins are hosted by an application that has foreseen specific extension points, and that actively calls these extension points. This is limiting the initiative what a Plug-in may contribute, but it keeps the integrity of the application. Here is an article in German, "Plug-Ins - Applikationsspezifische Komponenten", written together with Markus Völter. We explore some of the characteristics of Plug-Ins in comparism to (at that time more popular) container based component architectures.

SE-Radio has produced an interview about plug-ins that goes life in 2008.

Patterns

Plug-ins are mentioned in various places, e.g. in Martin Fowler's Patterns of Enterprise Application Architecture.
Probably the first pattern language on Plug-ins is my EuroPLoP 1999 submission on Patterns for Plug-ins. Beyond the mandatory concepts of hosting application and plug-in this article covers aspects of team organization and development process. Successful Plug-in development needs more than mastering the technical challenges - a thought you might spot in other areas as well. Below are the technical patterns that you need to start.

An updated version, taking into account the appearance of Eclipse but shortened to just the technical patterns, appeared in Pattern Languages of Program Design Volume 5.

Pattern: Plug-In

How can functionality be added late? How can the functionality be increased after shipping?
Factor out functionality, and place it in a separate component that is activated at run time. This component is called a Plug-In. The application defines functionality that it does not provide itself, but must be added by Plug-Ins. The application is shipped with a well defined interface for Plug-Ins (Plug-In Contract).
A Plug-In consists of executable code that the application loadsdynamically at run time. Each Plug-In complies with the defined interface. The application does not depend on a Plug-In internals, and often not on the presence of a particular Plug-In kind. Plug-Ins can be used to factor out essential functionality. In this case the presence of a particular Plug-In is required, and the application is always shipped with that Plug-In.
„Plug-In kind“ - different Plug-Ins are of the same kind when they conform to the same predefined interface. The OO analogon would be a superclass.
„Plug-In type“ - the Plug-In implementation denotes the type. The OO analogon would be a derived class.
„Plug-In instance“ - a currently active Plug-In. The OO analogon would be a class instance.

 Pattern: Plug-In Contract

How does the application define the Plug-In interface?
Publish the interface the Plug-In is expected to fulfill, and the interface offered to it. The Plug-In uses not only system services, but application services as well. Also the expected Plug-In functionality requires a custom interface. The figure shows the major components, and their dependencies.
Components provided by Plug-in and the hosting application

Plug-In Definition is the interface the framework requires from the Plug-In. The Plug-In is modeled as one or several abstract classes, together with their respective abstract factories or factory methods.
Plug-In adds specific knowledge to the application. It offers a factory or method that returns classes conforming to the expected interface. The internal implementation is hidden, and the visible class can serve as a Facade to it. The Plug-In may use services of the application, and must use the domain objects the framework provides.
Framework Interface defines the services and domain objects of the framework. Their implementation is hidden from the Plug-In by (abstract) factories, or product traders.
Implementation provides a process for execution, implements the framework services and domain objects, invokes the Framework Interface component, and activates the Plug-In by calling the factory and giving references to the framework objects.
All clients to the Plug-In can only access it through the Plug-In Definition component and interface, and the Plug-In can only access those instances and services published by the Framework Interface.

Pattern: Framework-Providing Application

How can a Plug-In create and use application domain objects?
The application offers a framework. This is a black box framework offering no insights in the host application, but defining opportunities for subclassing and parameterisation. Only part of the application is a framework. Other parts control loading and activating the Plug-Ins, or deal with completely unrelated stuff. Each interface for a Plug-In kind corresponds to a set of related „hot spots“.

Pattern: Plug-In RegistrationHow are the Plug-Ins known to the application?

The application defines a place where it looks for available Plug-Ins. Each Plug-In installs itself there.

Pattern: Plug-In Lifecycle

How can the application invoke and control the Plug-In?
The application defines the life cycle of the Plug-In. The life cycle for a Plug-In instance contains loading, activation, deactivation, and unloading. The life cycle for a Plug-In type includes registration when Active Registration is chosen. The transitions correspond to member functions within the Plug-In Definition to allow the Plug-In to react.
Both cycles must be cleanly differed especially when registration is done in the Active variant manner and may occur during run time of the application. They may be merged when only one Plug-In instance per kind may be active at a time.

Pattern: Plug-In Package

How to extend a Plug-In to turn it into a shippable component?
Define and ship the functional extension as a package consisting of many files of many different types. The Plug-In interface consists of the custom Plug-In Definition classes, and a number of additional files. The central Plug-In is packed together with related executables, Plug-Ins, resource files, and „little helpers“. Application requests resources and „little helpers“ in standard formats.
To determine which files and file kinds to pack, start by identifying the functions throughout the life cycle, that the functional extension is expected to fulfil. Then try to find technical interfaces for these functions. Prefer technical standards of a long (expected) lifetime, and use custom Plug-In Definitions where necessary.

Pattern: One Plug-In per Task

How can functional additions span multiple layers?
Define a distinct Plug-In Definition for each distinct task or domain. Provide a common identifier so that the application can activate the appropriate counterpart.
This allows for extension specific data and classes added to the model. This data can only be added by an extension specific Plug-In, and be viewed by another extension-specific Plug-In. The application cares for the data exchange and processing in between, and ensures that the corresponding Plug-In gets in control on the viewing side. Each extension consists of one Plug-In type of each predefined Plug-In kind.
Configurable application domain objects need a reference to the extension identifier. The application must also ensure that distinct extensions come with distinct identifiers. The extension must ensure that no version conflicts between different Plug-Ins occur.
Avoid addressing all extension functionality through one interface - it would look like a swiss army knife. Separate into consistent domains (and employ further standard file formats, see Plug-In Package).


(c) 2002..2008 Klaus Marquardt
home