Define “Pluggable”

This section defines what makes code pluggable. Some of the concepts here will be new to you, and that is OK. A programming paradigm cannot be created without exposing a number of concepts and terms. Many of these terms are explained in much greater depth later in the text. Knowing the basics around the rules of pluggability and how the macro concepts fit will aid learning them in greater depth later on.

Come back to this section over and over again. These rules should help you structure in your mind how to make truly pluggable software.

For Plugin Oriented Programming, virtually everything becomes pluggable. But what does it mean to write completely pluggable code? How can a paradigm allow you to author completely modular code? What is pluggable into what, and how?

To answer this, it is necessary to explain a number of concepts in Plugin Oriented Programming. These concepts will give an introductory foundation for what Plugin Oriented Programming is and how to train yourself to think in a world of plugins.

These concepts will also define how to avoid breaking pluggability. Each layer should be worked with in a pluggable way so as to avoid breaking the concepts of Plugin Oriented Programming. If these concepts are not broken then the application should achieve the goals of being truly pluggable.

Collections of Plugins - Subsystems

The first aspect of Plugin Oriented Programming is to consider all code as being broken up into individual plugins. Each plugin adheres to an interface definition. This concept of an interface definition makes each plugin, pluggable. This means that the interface definition becomes a critical component of your application and application thinking. The interface defined by a single plugin, through its very existence, defines part of the structure of your application.

Each plugin is replicable and extensible. If ever a plugin becomes too large or too unwieldy, then it needs to be broken up.

Plugins all belong to plugin subsystems, or Subs. The plugins present interfaces to communicate with the plugins, but Subs also present interfaces. We call these interfaces patterns.

Rule 1 of Pluggability

Subs contain Plugins. Plugins express an interface that is compatible with the pattern defined by the Sub. If plugins exist inside of a Sub that do not adhere to the interface of the sub, then they should be placed in another Sub. This other Sub can be new or an existing Sub.

Rule 2 of Pluggability

Plugins must be small, interfaces must be simple. If the code in a plugin cannot be reasonably explained to another engineer in a few hours - to the extent that the new engineer can extend or maintain that plugin - then it is in violation of pluggability.

The same applies to Subs, if the interface presented by a Sub cannot be reasonably explained to another engineer in a few hours - to the extent that the new engineer can extend or maintain that Sub - then it is in violation of pluggability.

The Hub and the Namespace

Plugin Oriented Programming functions based on the idea that a strict hierarchical namespace is maintained. This namespace defines where Subs and plugins live, as well as data. The Hub is the root of the namespace, and each Sub is available on the Hub or below another Sub. Each plugin lives in a Sub. Data is stored on the Hub so that it can be made available to the rest of the application and can be properly tracked.

Variables stored on the Hub should be stored next to the systems that have write access to them. If all plugins in a Sub have write access to a variable, then it is stored under the Sub’s namespace on the Hub. If multiple Subs need write access to a variable, then those Subs must be stored within a higher level Sub which contains that variable.

Finally, the namespace data, subs, plugins, and data should follow naming conventions to ensure consistency. Variables on the hub should always be all caps. Functions, Subs and plugins should always be underscore delimited, all lower case. Class names should always be CamelCase. These simple rules ensure that namespace collision probability is low, and presents predictable information to the next engineer.

Rule 1 of Namespace

Variables are stored on the Hub relative to Subs and plugins that have write access to the data. Any plugin or Sub deeper on the Hub than the variable has write access to the variable, by convention. If a plugin that is not below a variable wants write access, that variable needs to first be copied within that plugin’s respective namespace.

Rule 2 of Namespace

Conventions must be followed to ensure consistency and ease of transfer. Variables on the Hub should always be all caps. Functions, Subs and plugins should always be underscore delimited, all lower case. Class names should always be CamelCase.

App Merging

App Merging defines how multiple applications can be merged together. Since Plugin Oriented Programming applications all have a predictable namespace, those namespaces can be merged from multiple apps.

This makes entire applications natively pluggable! So long as a few simple rules of App Merging are not violated.

Everything goes on the Hub. If code is intended to be a library then it should be treated as such and developed as a standalone codebase that exposes library functionality. All code in a Plugin Oriented Programming codebase must exist in the structure of the Hub.

Plugins and Subs have initializers, much like classes in Python. These initializer functions are called __init__ and they are called when the plugin is first loaded. This allows for any environmental aspect required by the plugin or Sub to be set up. This is typically adding data structures to the Hub that are needed by the plugin or Sub. The initializers should never begin the execution of the code in the plugin or Sub. If they do initialize the code within the plugin or Sub then this can break App Merging because when the Sub is merged into another application it begins functioning. Those functions and patterns should only be executed at the behest of the merging application.

App Merging exists to allow applications to be split into small, workable codebases. The many codebases can then be merged together using a lightweight codebase to bring it all together. Just as Subs and plugins should be transferable to a new engineer within hours, so must an app. Apps should be small enough that they can be explained to a new engineer - to the extent that the new engineer can extend or maintain that App - within one to a few days. If this cannot be done, then a new app should be created to partition out and isolate the next chunk of code.

Rule 1 of App Merging

Everything needs to exist on the Hub. Writing library code outside of the Hub should be relegated to a separate codebase.

Rule 2 of App Merging

Don’t execute sequencing code inside of initializers, only set up the environment.

Rule 3 of App Merging

Apps should be small enough that they can be explained to a new engineer - to the extent that the new engineer can extend or maintain that App - within one to a few days. If this cannot be done, then a new app should be created to partition out and isolate the next chunk of code.