Background

With a history stretching back more than a decade, the IGB project has very deep roots, and represents many years of coding effort.  As the project has matured and gained traction in the community, the engineering effort behind the project has become increasingly sophisticated and professionalized.  In recent years, there has been a major effort on the part of the IGB development team to adopt widely recognized software industry best practices in all phases of our software development life cycle. One particular area we have been focusing on is adopting a modular service based architecture using the OSGi (open service gateway initiative) standard.

Why use a modular services-based architecture?

Less complexity, more understandable code

Refactoring IGB into self-contained "modules" of independent functionality reduces IGB's complexity and makes it easier to maintain and modify when new needs arise. Why does reduced complexity help? It helps in many ways, but one of the most obvious and important is that it reduces the amount of information a developer must keep in mind when reading or modifying a section of the code. Instead of working on the entire application all at once, a developer can focus on a single module, confident that any changes he or she makes will affect only that one module, provided the module interface stays the same. By enforcing a modular design - and restricting the points of contact between modules - we can build a more complex, powerful application for users while also gaining flexibility to adapt to change. This view of IGB as a system of cooperating modules with clear boundaries builds on the familiar concept of separation of concerns in object oriented programming. Rather than apply this principle at the class or package level, we apply it at the module-level, where modules are "bundles" of code responsible for clear tasks within the IGB application. By working with modules, we can more effectively manage our code base.

OSGi framework orchestrates module and object life cycles

IGB runs within an OSGi framework, a system and protocol for assembling and running applications composed of independent modules. When users launch IGB, they are really launching an OSGi "run-time," which then loads individual IGB modules - called "bundles" - into the run-time environment and instantiates objects as needed to satisfy module's dependencies on each other. To make methods available to other modules, a module developer inserts annotations that signal to the run-time that the method should be provided as an optional service to other modules in the IGB system. Only methods that are explicitly annotated as exportable are exposed to external modules. Moreover, developers rarely have to explicitly create or destroy many of the key objects in the IGB application. The OSGi run-time handles all of that.

Modularity and IGB Apps - a plug-able API for community contributors

The efforts we have made and continue to make to modularize the IGB code base have the incredibly beneficial side effect of leading to a software system which is already pluggable/extensible in a huge variety of ways.  The reason why a plugin API is the natural organic output of this refactoring effort is obvious. Each time we find existing functionality in code which is being isolated into a module we must evolve our APIs to allow for extensibility to accommodate. If for example, we find some code which is adding a menu option into the main IGB toolbar, we must then create mechanisms in the plugin API to allow for the addition of menus to this toolbar (e.g. the addition of an interface to implement).  These mechanisms are then available to all future module developers to leverage when writing their own extensions to IGB.  

IGB module overview

Module types

The IGB project contains more than 50 modules. These include:

  1. Library Modules - modules that contribute "utility" classes for consumption by other modules (e.g. guava, apache commons)
  2. API Modules - modules that only contain service interfaces, abstract classes, data model, or similar content.  (e.g. the igb-services-api module)
  3. Implementation Modules - modules that implement instances of the interfaces/abstract classes contained in API modules.  Their implementations typically will take the form of a registered OSGi service, requiring none of the internal content of a qbundle to be exposed.
  4. Blended Modules - Small modules which may both define API content and publish implementation content within the same module.  We do not consider this improper in most cases as long as the package exports are ensuring a proper separation of concerns and not exposing internals.  As a rule, only expose API, utility classes, and data model. 

The modularization effort of our project in ongoing, so there are some known violations within our own codebase of the best practices described above, but these will be resolved as our work continues.

Module classifications

Important IGB modules for external developers