Commit a0cd5838 authored by Christopher Guindon's avatar Christopher Guindon
Browse files

Merge branch 'zhoufang/develop/testRequest' into 'develop'

#51 Changed to new menu structure

See merge request !43
parents 21afb18a 4e41f831
Pipeline #6430 passed with stage
in 0 seconds
......@@ -53,101 +53,31 @@ pluralizeListTitles = false
unsafe = true
[[menu.main]]
name = "About"
url = "/about"
name = "OSGi in the Real World"
url = "/osgi-in-the-real-world"
weight = 1
[[menu.main]]
name = "About Us"
parent = "About"
url = "/about"
weight = 1
[[menu.main]]
name = "FAQ"
parent = "About"
url = "/about/faq"
weight = 2
[[menu.sidebar]]
name = "About"
url = "/about"
weight = 2
identifier = "about"
[[menu.sidebar]]
parent ="about"
name = "About Us"
url = "/about"
pre = "<i data-feather=\"users\"></i>" # https://feathericons.com/
weight = 1
[[menu.sidebar]]
parent ="about"
name = "FAQ"
url = "/about/faq"
pre = "<i data-feather=\"help-circle\"></i>" # https://feathericons.com/
weight = 2
[[menu.main]]
name = "Members"
url = "/membership/members/"
weight = 1
name = "Membership"
url = "/membership"
weight = 3
[[menu.main]]
name = "Resources"
url = "/resources"
weight = 1
name = "Community"
url = "/community"
weight = 4
[[menu.main]]
name = "Documentation"
parent = "Resources"
url = "https://docs.osgi.org/"
weight = 1
[[menu.main]]
name = "Specification Project"
parent = "Resources"
url = "https://projects.eclipse.org/projects/technology.osgi"
weight = 1
weight = 5
[[menu.main]]
name = "Technology Project"
parent = "Resources"
url = "https://projects.eclipse.org/projects/technology.osgi-technology"
weight = 1
[[menu.main]]
name = "What is OSGi?"
parent = "Resources"
url = "/resources/what-is-osgi"
weight = 2
[[menu.main]]
name = "Modularity"
parent = "Resources"
url = "/resources/modularity"
weight = 2
[[menu.main]]
name = "Complexity, Modularity and Business"
parent = "Resources"
url = "/resources/complexity-modularity-and-business"
weight = 2
[[menu.main]]
name = "Where to Start"
parent = "Resources"
url = "/resources/where-to-start"
weight = 2
[[menu.main]]
name = "Architecture"
parent = "Resources"
url = "/resources/architecture"
weight = 2
[[menu.main]]
name = "Blog"
url = "https://blog.osgi.org/"
weight = 2
name = "Getting Started"
url = "/getting-started"
weight = 6
---
title: "About Us"
date: 2018-04-05T16:09:45-04:00
#hide_page_title: true
layout: "single"
---
......
---
title: "Frequently Asked Questions"
seo_title: "Frequently Asked Questions"
date: 2018-04-07T16:09:45-04:00
type: "faq"
layout: "section"
---
Last Updated: February 26, 2021
<br/>
{{< faq >}}
\ No newline at end of file
---
title: "Community"
seo_title: "Community - Eclipse OSGi"
keywords: ["Eclipse OSGi community", "OSGi open source community", "open source OSGi"]
date: 2022-05-30T10:10:45-04:00
---
---
title: "Where to Start"
date: 2018-04-05T16:09:45-04:00
#hide_page_title: true
title: "Getting Started"
date: 2022-05-30T10:10:45-04:00
layout: "single"
---
......
......@@ -9,3 +9,4 @@ date: 2021-02-10T16:09:45-04:00
links: [[href: "https://accounts.eclipse.org/contact/membership/osgi", text: "Contact Us About Membership"]]
---
{{< all-members >}}
---
title: "Explore Our Members"
seo_title: "Explore our members - Eclipse OSGi"
description: "Discover our Eclipse OSGi members."
keywords: ["Eclipse OSGi members", "OSGi open source members", "open source OSGi"]
aliases:
- /members/
- /member/
outputs:
- HTML
- JSON
- RSS
hide_sidebar: true
container: "container-fluid container"
---
{{< all-members >}}
\ No newline at end of file
---
title: "OSGi in the Real World"
date: 2022-05-30T10:10:45-04:00
layout: "single"
---
---
title: "Architecture"
date: 2018-04-05T16:09:45-04:00
#hide_page_title: true
layout: "single"
---
[OSGi technology](../what-is-osgi/) is a set of _[specifications](https://docs.osgi.org/specification/)_ that define a dynamic component system for Java. These specifications enable a development model where an application is composed of several components which are packaged in _bundles_. Components communicate locally and across the network through _services_.
An application in this context represents the functionality desired by the organization. For example, an expense account reporting application or a payroll application. The goal is to make the application code as small as possible because that code is not reusable. It is the code that is unique for the application and usually highly coupled to a large set of components. That, however, works two ways. Since applications are not reusable extra dependencies are very cheap.
Components are the reusable building blocks, i.e., the bricks, the components provide the implementation code. Since components should be reusable, they should watch their dependencies because any dependency will be added to any application that uses this component.
The OSGi specifications enable components to hide their implementations from other components while communicating through services, which are objects that are explicitly shared between components.
Services are an innovation that OSGi brought to the table. Services are the reified links between components. In a well designed OSGi system, all links between components go through a service. Services have an API that is defined in a Java _package_. The API consists of classes and/or interfaces that are needed for the collaboration between the provider of the service and the consumer of the service. (Note that provider and consumer do not imply implementer/user of an interface).
This surprisingly simple model has far reaching effects for almost any aspect of the software development process.
A bundle is the OSGi name for a module, it packages the components with their resources. Bundles are explicit in their requirements on the environment and the capabilities they will provide to the environment. For example, a bundle will express what Java packages it needs in what version.
### Component Systems
Components have been on the horizon for a long time now, however so far they failed to make good on their promises. OSGi is the first technology that succeeded with a component system that solves many real software development problems. Adopters of OSGi technology see significantly reduced complexity in almost all aspects of development. Code is easier to write and test, reuse is increased, build systems become significantly simpler, deployment is more manageable, bugs are detected early, and the runtime provides an enormous insight into what is running. **Most importantly, it works**.
OSGi technology was developed to create a collaborative software environment. We were not looking for the possibility to run multiple applications in a single VM. Application servers do that already. No, the problem were addressing was harder. We wanted an application to _emerge_ from the collection of different reusable components that had no a-priori knowledge of each other. Even harder, we wanted that application to emerge from the _dynamic_ assembly of these components.
For example, you have a home server that is capable of managing your lights and appliances. A component could allow you to turn your lights on and off using a web page. Another component could allow you to control your appliances via a text message. The goal was to allow functions to be added without requiring the developers to have an intricate knowledge of each other. This makes it possible for components to be developed and added and removed independently and without affecting the operation of any other function.
### Layering
OSGi has a layered model that is depicted in the following figure.
![layering-osgi](/images/resources/layering-osgi.png)
- Bundles – Bundles are the OSGi components made by the developers.
- Services – The services layer connects bundles in a dynamic way by offering a publish-find-bind model for plain old Java objects.
- Life-Cycle – The API to install, start, stop, update, and uninstall bundles.
- Modules – The layer that defines how a bundle can import and export code.
- Security – The layer that handles the security aspects.
- Execution Environment – Defines what methods and classes are available in a specific platform.
### Modules
The fundamental concept that enables such a system is _modularity_. Modularity, simplistically said, is about assuming less. Modularity is about keeping things local and not sharing. It is hard to be wrong about things you have no knowledge of and make no assumptions about them. Therefore, modularity is at the core of the OSGi specifications and embodied in the _bundle_ concept. In Java terms, a bundle is a plain old JAR file. However, where in standard Java everything in a JAR is completely visible to all other JARs, OSGi hides everything in that JAR unless explicitly exported. A bundle that wants to use another JAR must explicitly import the parts it needs. By default, there is no sharing.
The code hiding and explicit sharing provides many benefits (for example, allowing multiple versions of the same library being used in a single VM), the code sharing was only there to support the OSGi _services_ model. The services model is about bundles that collaborate.
To find out more about why modularity is so important, how it can reduce complexity and facilitate agility and evolvability read on [here](../modularity/).
### Services
We needed the service model because Java shows how hard it is to write collaboratively with only class sharing. The standard solution in Java is to use _factories_ that use dynamic class loading and statics. For example, if you want a DocumentBuilderFactory, you call the static factory method DocumentBuilderFactory.newInstance(). Behind that façade, the newInstance method tries every class loader trick in the book (and some that aren’t) to create an instance of an implementation subclass of the DocumentBuilderFactory class. Trying to influence what implementation is used is non-trivial (services loader model, properties, conventions in class name), and usually global for the VM. Also it is a _passive_ model. The implementation code cannot do anything to advertise its availability, nor can the user list the possible implementations and pick the most suitable implementation. It is also a static model. Once an implementation hands out an instance, it cannot withdraw that object. Worst of all, the factory mechanism is a _convention_ used in hundreds of places in the VM where each factory has its own unique API and configuration mechanisms. There is no centralized overview of the implementations to which your code is bound. In other words, a nightmare.
The solution to all of these issues is simply the OSGi _service registry_. A bundle can create an object and register it with the OSGi service registry under one or more interfaces. Other bundles can go to the registry and list all objects that are registered under a specific interfaces or class. For example, a bundle provides an implementation of the DocumentBuilder. When it gets started, it creates an instance of its DocumentBuilderFactoryImpl class and registers it with the registry under the DocumentBuilderFactory class. A bundle that needs a DocumentBuilderFactory can go to the registry and ask for all available services that extend the DocumentBuilderFactory class. Even better, a bundle can wait for a specific service to appear and then get a call back.
A bundle can therefore _register_ a service, it can _get_ a service, and it can _listen_ for a service to appear or disappear. Any number of bundles can register the same service type, and any number of bundles can get the same service. This is depicted in the following figure, which is what is generally referred to as a _broker pattern_.
![services](/images/resources/services.png)
What happens when multiple bundles register objects under the same interface or class? How can these be distinguished? Firstly, in many cases it is not important to distinguish between individuals. Otherwise the answer is properties. Each service registration has a set of standard and custom properties. An expressive filter language is available to select only the services in which you are interested. Properties can be used to find the proper service or can play other roles at the application level.
Services are dynamic. This means that a bundle can decide to withdraw its service from the registry while other bundles are still using this service. Bundles using such a service must then ensure that they no longer use that service object and drop any references. We know, this sounds like significant complexity but it turns out that helper classes like the Service Tracker and frameworks like Declarative Services can remove the pain and the advantages are quite large. Service dynamics were added so we could install and uninstall bundles on the fly while other bundles could adapt. That is, a bundle could still provide functionality even if the http service went away.
We found that the real world is actually dynamic and many problems are a lot easier to model with dynamic services than static factories. For example, a Device service could represent a device on the local network. If the device goes away, the service representing it is unregistered. This way, the availability of the service models the availability of a real world entity. This works out very well in, for example, the distributed OSGi model (Remote Services) where a service can be withdrawn if the connection to the remote machine dies. It also turns out that the dynamics solve the initialization problem. OSGi applications do not require a specific start ordering in their bundles.
We found that the service registry significantly simplified application code because it handles so many common patterns. The effect of the service registry has been that many specialized APIs can be modeled with the service registry. Not only does this simplify the overall application, it also means that standard tools can be used to debug and see how the system is wired up.
OSGi services should be looked upon as a _software design primitive_. In the eighties objects were seen as weird curiosities as structs with function tables. Only when polymorphism, inheritance, and data hiding became design primitives in people’s mind did we start to reap the benefits. This is similar for OSGi services. They can be extremely lightweight (not much more than a Java Object) but have semantics that go way beyond what a plain Object can do.
Though the service registry accepts any object as a service, the best way to achieve reuse is to register these objects under (standard) interfaces to decouple the implementer from the client code. This is the reason for the OSGi [Compendium specifications](https://docs.osgi.org/specification/). These specification define a large number of standard services, from a Log Service to a Measurement and State specification. All these standardized services are described in great detail.
That said, the approach to decouple the API from the implementation pays off in even the smallest of problems. It is our experience that even trivial problems tend to grow over time. Separating the API from the implementation makes almost every aspect of the software development process simpler today and certainly for the long term. It is our recommendation that organization wide APIs are carefully managed by organizations.
### Declarative Services & Configuration
Two of these standardized services in OSGi are the Configuration Admin service and Declarative Services (DS). Though these service are just a few of the many compendium services they have a special role. These services provide functionality that is very hard to evaluate from the outside because they have no counterpart in in other systems.
Declarative Services makes writing a service implementation as simple as writing a POJO with a few annotations. Though there are other systems that do similar injections as Declarative Services, these other systems ignore time and dependencies. By handling time and (dynamic) dependencies without any code overhead OSGi provides a toolbox that is as innovative as objects were in the nineties. Declarative Services has received a [number of updates and enhancements with OSGi R7](https://blog.osgi.org/2018/03/osgi-r7-highlights-declarative-services.html) including support for constructor injection, activation fields, enhancements to component property types, and a number of smaller enhancements.
In a similar vein, Configuration Admin can be used to not only configure service implementations, it can also control the lifecycle.
DS and Configuration Admin make it possible to create components that are completely configured through Configuration Admin, including their lifecycle and so no configuration API is required. This is a feature that has no counterpart in other environments but the value of this is hard to over estimate.
### Deployment
Bundles are deployed on an OSGi _framework_, the bundle runtime environment. This is not a container like Java Application Servers. It is a _collaborative environment_. Bundles run in the same VM and can actually share code. The framework uses the explicit imports and exports to wire up the bundles so they do not have to concern themselves with class loading. Another contrast with application servers is that the management of the framework is standardized. A simple API allows bundles to install, start, stop, and update other bundles, as well as enumerating the bundles and their service usage. This API has been used by many _management agents_ to control OSGi frameworks, examples are as diverse as the Knopflerfish desktop and the Bosch OSGi management system.
### Implementations
The OSGi specification process requires an implementation for each specification and this has to be available under an open source license. There have also always been commercial implementations as well as other open source implementations. Currently, there are four open source implementations of the framework ([Apache Felix](https://felix.apache.org/), [Eclipse Concierge](https://www.eclipse.org/concierge/), [Eclipse Equinox](https://www.eclipse.org/equinox), and [Knopflerfish](http://www.knopflerfish.org/)) and way too many to count implementations of OSGi services. The [OSGi Specifications Implementation wikipedia page](https://en.wikipedia.org/wiki/OSGi_Specification_Implementations) provides a good overview of many of these. Its great to see more and more commercial and open source projects delivering their projects and products as OSGi bundles. We are pleased to assist anyone who is thinking of doing this and you can ask for help on the [OSGi users list](https://accounts.eclipse.org/mailing-list/osgi-users).
### Further reading
- [How to get Started with OSGi?](../where-to-start/)
---
title: "Modularity"
date: 2018-04-05T16:09:45-04:00
#hide_page_title: true
layout: "single"
---
## Why is Modularity so Important?
- Modularity makes complexity manageable
- Modularity enables parallel work
- Modularity is tolerant of uncertainty
By “tolerant of uncertainty” we mean that particular elements of a modular design may be changed after the fact and in unforeseen ways: see [Design Rules, Volume 1 The Power of Modularity](https://mitpress.mit.edu/books/design-rules-volume-1).
[Techopedia](https://www.techopedia.com/definition/24772/modularity) defines modularity, from a software engineering perspective as referring
> … to the extent to which a software/Web application may be divided into smaller modules. Software modularity indicates that the number of application modules are capable of serving a specified business domain.
To successfully implement Modularity, the internal implementation details of a Module must be shielded from the Module’s external environment. The external environment being the aggregate of all other modules, the underlying runtime and higher level Services. The only permissible interactions between the Module, and its host ‘Environment’, are then via the Module’s (in a software context) public Interfaces.
Once achieved, the internal mechanisms within a Module are decoupled from the external environment.
Regarding the importance of Modularity in Software, which of course includes Java Modularity, [Parnas](https://en.wikipedia.org/wiki/David_Parnas) in his seminal paper [On the Criteria to be Used in Decomposing Systems into Modules](http://repository.cmu.edu/cgi/viewcontent.cgi?article=2979&context=compsci), states…
> “The major advancement in the area of modular programming has been the development of coding techniques and assemblers which (1) allow one module to be written with little knowledge of the code in another module, and (2) allow modules to be reassembled and replaced without reassembly of the whole system. This facility is extremely valuable for the production of large pieces of code…”
He goes on to explain that…
> “… the impact of change on a Modular composite system is dictated by how the system was decomposed. If a small change in a single Module causes a cascade of many downstream changes in other modules; then Modules in the system are **tightly-coupled**. However if the change results with minimal/no downstream changes, then the Modules in the System are **loosely-coupled**.”
## What Fundamental Problem Does Modularity Solve?
> **Answer: Software Complexity**
Agility, Adaptability and Low Maintenance are essential characteristics required by tomorrow’s software ecosystems (e.g., Smart City and Industry 4.0). However, as DARPA realize, today’s software systems are complex and fail to meet these objectives.
> Modern-day software systems, even those that presumably function correctly, have a useful and effective shelf life orders of magnitude less than other engineering artifacts…
>
> while an application’s lifetime typically cannot be predicted with any degree of accuracy, it is likely to be strongly inversely correlated with the rate and magnitude of change of the ecosystem in which it executes.
-- [Building Resource Adaptive Software Systems – The DARPA BRASS Initiative 2015](https://www.darpa.mil/program/building-resource-adaptive-software-systems)
Realizing this, DARPA issued the challenge to create software systems that avoid obsolescence; to create software ecosystems that are able to run for more than 100 years. Such software ecosystems must be economically sustainable over these extended periods, and to achieve this longevity they must be cost-effective to adapt and evolve and be simple to maintain, or more probably, be self-maintaining.
While this DARPA initiative is recent, software scientists have been aware of these foundational issues since the early 1970’s. Notable insights into the nature of this problem include:
**Gall’s Law (1975)**
> A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.
**Lehman’s Law (1974)**
> As a system evolves, its complexity increases unless work is done to maintain or reduce it.
Yet, a decade into ‘virtualization’ and more recently Containerisation and these maintainability and evolvability goals seem more elusive than ever.
Why is this so?
While ‘Structural Complexity’ and ‘Change’ are challenges shared by all engineering disciplines; it is perhaps the fluidity and rate of change that uniquely differentiates software engineering; perhaps aligning it closer to Biological or Social Systems.
And so, it is perhaps to those disciplines we should look to for guidance?
## Complexity, Change and the Role of Modularity
Biological, Ecological and Social systems are neither **chaotic** or completely **deterministic** in behavior; rather they are **Agile** and able to **Adapt** to the environments within which they find themselves embedded. Systems that achieve this while maintaining internal organizational patterns are collectively referred to as Complex Adaptive Systems (CAS).
> All Complex Adaptive Systems (CAS) are composed of a hierarchy of structural layers; each layer internally modular; thereby building an intricate hierarchy of boundaries and signals.
-- [Signals and Boundaries – John Holland](https://mitpress.mit.edu/books/signals-and-boundaries)
### Cohesion & Loose Coupling
To accommodate structural change Systems must attempt to localize and/or minimize the effects of Change.
To achieve this, components within the System that are closely related
- that must change in unison,
- that must evolve together,
need to be colocated together ideally within the same logical unit; i.e., a Module.
Meanwhile, components that evolve at different rates, and/or could be used separately in different runtime contexts, should be in separate Modules, and these Modules should be `Loosely Coupled` via the published Interfaces that change much more slowly over time.
In software engineering these principles are referred to as the [Principles of Package Cohesion](https://en.wikipedia.org/wiki/Package_principles#Principles_of_package_coupling) which state that:
- Reuse-release equivalence principle (REP) – The unit of reuse is the unit of release.
- Common-reuse principle (CRP) – Classes that aren’t reused together should not be grouped together.
- Common-closure principle (CCP) – Classes that change together belong together.
Hence to enable change, Modules must be **loosely coupled** to each other.
### Semantic Versioning
Loose coupling cannot be achieved if Modules refer to each other explicitly by unique names; e.g., in the following diagram Model ∑ explicitly references a dependency on the named Module Ω.
![Diversity](/images/resources/Diversity.png)
Rather, to enable substitution, Module relationships need to be expressed in terms of the **Capabilities** they expose to their Environment, and what they **Require** from their Environment. We see that Module ∑ Requires a Capability X, and that this Capability can be provided by any one of the Modules Ω,µ,π. Given the diverse set of implementations of Service X, substitution is possible, and so change is possible.
It is also useful to have some form of mechanism to communicate the impact of a change, and in the context of software engineering this is achieved by [Semantic Versioning](https://semver.org/).
![SemDiversity](/images/resources/SemDiversity.png)
As shown, Module ∑ from its perspective now states a constraint on the usable versions of Service X. The constraint [2.0.0, 3.0.0) states that only Services at versions 2.0.0 or higher, but less than 3.0.0, will be considered; hence π is no longer a candidate but Ω,µ remain valid options.
### Dependencies and Topology
The [Principles of Package Cohesion](https://en.wikipedia.org/wiki/Package_principles#Principles_of_package_coupling), provide guidance concerning the inter-relationship between Loosely-Coupled Modules:
- Acyclic dependencies principle (ADP) – The dependency structure between packages must not contain cyclic dependencies.
- Stable-dependencies principle (SDP) – The dependencies between packages should be in the direction of the stability of the packages. A package should only depend upon packages that are more stable than it is.
- Stable-abstractions principle (SAP) – Packages that are maximally stable should be maximally abstract (i.e. public Module Interfaces). Unstable packages should be concrete (Module implementations). The abstractness of a package should be in proportion to its stability.
These rules attempt to minimize the _impact of change_ upon the graph topology created by the inter-dependent set of Modules.
It is also worth considering the work of [Zanetti and Schweitzer](https://arxiv.org/abs/1201.3771) on using complex network theory to estimate the coherence between the modularity of the dependency network of large open source Java projects and their decomposition in terms of Java packages.
### Structural Hierarchy
With respect to structural hierarchy Parnas states…
> “The existence of the hierarchical structure assures us that we can “prune” off the upper levels of the tree and start a new tree on the old trunk. If we had designed a system in which the “low level” modules made some use of the “high level” modules, we would not have the hierarchy, we would find it much harder to remove portions of the system, and “level” would not have much meaning in the system.”
and
> “We must conclude that hierarchical structure and “clean” decomposition are two desirable but independent properties of a system structure.”
Hence Parnas sees **Hierarchy** and **Modularity** as orthogonal concerns. However, this is not quite the case.
Something strange happens when we apply Modularity to a structure. Let’s take Java as an example;
- Raw code is structured into abstractions we call `Classes` – the finest level of Modularity.
- As we now need to manage a very large number of `Classes` we group them into abstractions we call `Packages`.
- As we need to manage the interactions between a large number of `Packages` we group `Packages` into abstractions we call OSGi Bundles.
- Fine-grained runnable Services are then created from groups of Bundles.
- These runnable microservices are then wired together to create the desired application or business service
The introduction of Modularity at one structural layer actually introduces a new higher layer of structural abstraction.
Modularity and the runtime structural Hierarchy are therefore actually closely related concepts.
If implemented correctly, as we climb up through this structural hierarchy cohesion should decrease and loose-coupling increase.
![ComplexityModularity3-1](/images/resources/ComplexityModularity3-1.png)
However, now for each new layer of this hierarchy, we must address the questions:
- Which set of Modules are required to produce the desired functionality for the next structural layer?
- How do these Modules communicate at runtime: if co-located, if distributed?
- What is the Module lifecycle?
- At which layer’s should the Composite Entities be configured, and by whom?
Hence, by creating new structural abstractions we’ve created new layers of complexity. Moreover, the Actors that need to deal with this complexity are unlikely to be the Developers that wrote the original code. Indeed, as is discussed in the next section on Measuring Complexity, this is actually undesirable.
This sounds like a lot of effort? So are we really reducing Complexity? How are we winning?
## Measuring Complexity
How can you measure complexity?
Intuitively one might expect software complexity to grow with respect to the number of links (i.e. links being lines of code calling a method or using a field) inside the code base. In the following diagram we see that module A has 9 internal links, hence a reasonable complexity measure might be proportional to 9<sup>2</sup>. Meanwhile, for the Modular alternative, we see that the combined complexity estimate (Module B and C together) is 3<sup>2</sup> + 6<sup>2</sup>, which is almost half.
![ComplexityModularity1](/images/resources/ComplexityModularity1.jpg)
### Quantitative Measures
Variations on the above approach have been investigated since the early 1970’s. For example, in 1977 [Halstead proposed](https://en.wikipedia.org/wiki/Halstead_complexity_measures) that software Complexity metrics should reflect the implementation or expression of algorithms, but be independent of their execution on a specific platform. Halstead’s approach mirrored Physics’ approach to the measurement of invariant properties of matter (like the volume, mass, and pressure of a gas) and the relationships between these properties (Boltzman Ideal Gas equation).
The problem with such studies is that an absolute complexity measure – however derived – is abstract and means nothing in isolation. Such measures are relative in nature and we need to be able to map relative changes in complexity through to measurable consequences.
### Qualitative Measures
Quantitaive Complexity measures provide a more direct route to cost/benefit analysis.
Qualitative measures of software complexity can be traced back to Scott Woodfield’s research in 1979 [An Experiment on Unit Increase in Problem Complexity](https://www.computer.org/web/csdl/index/-/csdl/trans/ts/1979/02/01702600.pdf). With the participation of 48 experienced developers, Woodfield conducted a series of experiments to investigate how different types of modularization and comments relate to programmers’ ability to understand, correct and modify programs.
<a id="glass"></a>Woodfield’s research is summarised by Robert Glass in his book [Facts and Fallacies of Software Engineering](https://en.wikipedia.org/wiki/Robert_L._Glass) – sometimes referred to as **Glass’s Law** which states:
> For every 25% increase in problem complexity (F), there is a 100 percent increase in complexity (C) of the software solution.
As demonstrated in the blog post [The Equation every Enterprise Architect Should Memorize – Roger Sessions](https://simplearchitectures.blogspot.co.uk/2012/03/equation-every-enterprise-architect.html), this expression can be recast into:
> A Module with b functions is 10<sup>log(C) x log(b) / log(F)</sup> times more complex than a Module that contains just 1 of the functions.
If we apply Glass’s complexity measure to the previous example we find the following:
- Module A with 9 functional units gives a value of 9<sup>3.11</sup> = 928,
- whereas the combined complexity of Modules B & C are 75 + 149 = 224.
_Note: The exponent <sup>3.11</sup> in Glass’s law is derived via a qualitative process. Hence it is reasonable to adjust this value if data from your environment indicates that it should be higher or lower._
### Complexity & Hierarchy
Armed with **Glass’s Law** we can now revisit the previous Complexity v.s. Hierarchy discussion.
We will start by seeing what happens if we ignore any Cohesion concerns and break our pet Monolith into 9 isolated Modules; each Module representing one function. These functions are independently deployed into a traditional Production environment as 9 independent microservices.
![Microservices](/images/resources/Microservices.png)
This process results in a massive decrease in Developer complexity: i.e. 928 to 9 × 1. However, as the traditional runtime has no automatic assemble/orchestration capabilities, the runtime complexity exposed to Operations explodes from the single running monolith (Complexity 1) to having to configure a number of inter-related microservices (Complexity 9<sup>3.11</sup> = 928). Without appropriate runtime automation, this, therefore, becomes an Operational nightmare.
To realize the significant benefits created by Modularity, the release toolchain and runtime platform must be capable of automatically Orchestrating and Assembling the required runtime Composite System from the available Modules. This **shields** Operations from the structural details of the composite system and presents them with a single simple entity to manage.
![CompositeSystem](/images/resources/CompositeSystem.png)
Once achieved, we have now reached the point where:
- Developer complexity is reduced by a factor of 100 (i.e. 9 / 932) and
- The simplicity of the runtime monolith is preserved for Operations.
By using release tooling and the runtime to automatically manage assembly and orchestration results in an environment that environment is orders of magnitude simpler and more flexible.
## Measuring Modularity
Two questions often arise:
- How modular should I be?
- How can you measure modularity of your project?
[Alenezi and Zarour](https://www.researchgate.net/publication/275955308_Modularity_Measurement_and_Evolution_in_Object-Oriented_Open-Source_Projects) in their paper “Modularity Measurement and Evolution in Object-Oriented Open-Source Projects” confirm that:
> Enhancing our ability to understand and capture software evolution is essential for better software quality and easier software maintenance process. One of the software characteristics that helps in achieving this is software modularity.
This work identified that there are some successful approaches to measuring modularity, however the answer to 'How modular should I be?' really is …it depends… on the specifics of your project and which level of the structural hierarchy your are responsible for.
## To Conclude
Software Complexity is a foundational problem and Modularity is the solution to that problem. However, Modularity is not a one time apply and forget activity. The Modularization process creates a structural hierarchy and introduces new management considerations for each new layer in that hierarchy.
However, even after accounting for the new layers of structural complexity created by Modularity, the reduction of overall System Complexity is profound.
Of course, the most important complexity measure, and the one of most interest to senior management is expressed in the Total Cost of Ownership (TCO) of the System.
---
title: "What is OSGi?"
date: 2018-04-05T16:09:45-04:00
#hide_page_title: true
layout: "single"
---
## OSGi, The Dynamic Module System for Java
OSGi technology is composed of a set of specifications, implementations for each specification, and a set of test compatability kits for each specification that together define a dynamic [module system](../modularity) for Java. OSGi provides a vendor-independent, standards-based approach to modularizing Java software applications and infrastructure. Its proven services model enables application and infrastructure modules to communicate locally and distributed across the network, providing a coherent end-to-end architecture. OSGi specifications have been extensively field-tested and are ready to use. Currently on release 7, OSGi has provided a stable and evolvable technology platform for development for open source projects and commercial products for almost two decades.
Widely adopted, yet often unreported, OSGi is used in a broad array of open source and commercial products and solutions ranging from business and life critical applications through to the more mundane. Starting out in set top boxes and residential gateways OSGi has today been adopted for solutions in IoT, M2M, Smart Home, Telematics, Assisted Living, Healthcare, Automotive, Media, Control Systems, Energy Management, Smart Meters, Telecommunications, Enterprise Software Platforms and Robotics, to name a few.
OSGi [significantly reduces complexity](../modularity#complexity) in almost all aspects of development: code is easier to write and test, reuse is increased, build systems become significantly simpler, deployment is more manageable, bugs are detected early, and the runtime provides an enormous insight into what is running.
### Get started with OSGi
Reuse components to build and manage your highly complex systems. Make code easier to write, test and reuse. Manage dynamic deployment. Detect bugs earlier. Deploy remotely. Detect and solve problems you might not be aware of right now.
If you’re developing software in Java, then OSGi should be in your tool chest.
### Why OSGi?
OSGi provides a [modular architecture](../modularity) for today’s large-scale distributed systems as well as small, embedded applications and device networks. Building systems from in-house and off-the-shelf modules significantly increases the reuse of software products and solutions and extends their lifecycle, reducing development and maintenance expenses. The OSGi programming model realizes the promise of component-based systems.
OSGi technology is successful because it provides a very mature, field proven, component system that works in a large number of environments. The OSGi component system is used to build any type of application ranging from the simple to highly complex applications like IDEs, application servers, email systems, content management systems, application frameworks, residential gateways and onboard telematics systems. OSGi has enjoyed wide adoption across a broad range of industries and uses including IoT, M2M, Smart Home, Telematics, Assisted Living, Healthcare, Automotive, Media, Control Systems, Energy Management, Smart Meters, Telecommunications, Enterprise Software Platforms and Robotics.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment