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.
-
- 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
|