.. _hub_overview: .. highlight:: python ===================== Understanding The Hub ===================== The hub is the central feature of Plugin Oriented Programming. I first developed the idea of the hub when I implemented pop in Julia. I realized that I needed to pass in a namespace for all of the plugins to exist on. Before that I had been trying to maintain links between plugin systems on the python module level. Working in Julia forced me to think about the problem differently. The hub therefore allows for plugin systems to be separated from the module systems inside of (in this case) Python. Once I had a separate namespace to work with it became easy to decouple memory management as well. I had created a data hierarchy. This is a very critical part of POP, memory and variable management is very important to how software is written and I realized that a new exploration of how to approach the problem could yield new results. Namespaces Beyond Silos ======================= The first thing to think about the hub is that it defines the complete structure of your application while delivering a new way to think about memory management. Namespaces, beyond silos. In classical Object Oriented Programming we follow a model of variable namespaces where we isolate memory onto the stack and the heap. The clean, well defined stack of a function, and the broad mess of data, aptly called the heap. To deal with the open-ended flexibility of the heap, memory management evolved into an adjacency model. Data that is to be used by certain functions should be adjacent to said functions inside of class instances. This made memory management on the heap (arguably) more elegant. You don't need to manage a heap of variables, but instead a collection of class instances. This has generally been seen as an improvement, an evolution. But this created a reverse issue, data increasingly became isolated to silos, encapsulation offered control, but introduced over encapsulation. The idea that data became too isolated and hard to get access to. It is a common issue that data needs to be synced between classes and instances and that communication between classes and instances can be troublesome. There now exist many ways to solve this problem, but they often remain messy and convoluted. Object Oriented Programming also introduced the concept od public, protected and private variables and functions. This is an excellent tool for defining how the developer wants to scope the use of functions, variables and methods. POP pushes beyond OOP without sacrificing the benefits. The hub presents a namespace that can be used to place data onto a world readable medium, solving over encapsulation, while still communicating to the developer how to interact with data and still allowing data to be private to functions, modules, classes, and instances. Using Hub Namespaces ==================== The hub namespace is made to link to the physical layout of the code. Therefore the location of data on the hub also defines the location in code of where and how the data is to be used. Lets start by going over the hub's layout. hub --- The hub is the root object, if you decide to place variables on the hub, it is assumed that these variables are world read/writable. It is rarely, if ever, permissible to place variables directly on the hub. This is because it dirties the root namespace and creates issues for app merging because you have a higher likelihood of creating app merging conflicts. hub.sub{.sub.sub...} -------------------- Below the hub is where you get your subs. The subs are really the sole intended occupants of the hub. A sub is a named collection of plugins. In this case, variables that exist on the sub are intended to be writable only to plugins found within the sub. A sub can also have a nested sub. This is a sub within a sub that has its own plugins. A nested sub is intended to have write access to the parent sub's variables. This allows for communication dicts, queues, etc., to exist on a higher level sub to facilitate communication between lower level sub's modules. The sub level is a very common level to place variables. The nature of plugins is such that they need intercommunication, but that communication also needs to be limited! It should not experience interference from external plugin systems. Keep in mind that this is the data from external plugin systems. Many patterns are built to present external communication interfaces to other subs. This is a perfectly acceptable reason to have external subs send data into a sub. This is typically done by calling a function within the sub, so the data is still written from within the sub itself. This allows for the data input to be controlled and kept clean. hub.sub.mod ----------- The module layer allows for data that is isolated to the use of the specific module. This allows for patterns that call functions in modules repeatedly to persist data. Naming Conventions ================== Because the namespaces can collide it makes sense that objects on the hub should follow namespace rules. Use this document to define access and naming conventions. Variable Names -------------- Variable names stored on the hub in any location should always be all caps, following the Python convention of module level variables: .. code-block:: python hub.sub.INQUE = asyncio.Queue() Sub Names --------- The names of subs should always be underscore delimited and lower case: .. code-block:: python hub.sub Module Names ------------ The names of modules should always be underscore delimited and lower case: .. code-block:: python hub.sub Function Names -------------- The names of functions should always be underscore delimited and lower case: .. code-block:: python hub.sub.mod.function() Class Names ----------- Class names should always be CamelCase: .. code-block:: python hub.sub.mod.MyClass()