Modular programming has been around since the 60s and is a foundation of any good software architecture. Across many industries that were once hardware-dominated, software architecture is surfacing as a critical bottleneck for delivering the best products to the market first. Simultaneously, the share of R&D spending on software development is increasing rapidly.
The main issue is that software has grown organically within these products. If the perspective hasn't been raised and a unified modular software architecture has been set up, there is an evident risk that you end up with many different monolithic software platforms, each designed for a narrow subset of your products. This issue makes your development slow and costly, with poor output.
One could argue that lack of strategic software modularity is the main reason traditional hardware-first companies have difficulty competing with new, focused competitors that don't have the burden of an existing portfolio.
In this blog post, we will explain what software modularity is, why it matters to your business, and what you can do to improve your software.
Software modularity is measured by how well software is decomposed into smaller pieces with standardized interfaces. It is analogous to modularity for hardware. We want to create products by combining reusable chunks of code, so you only implement a feature or functionality once and then maximize reuse.
A software module exposes its interface to other modules, both internally within the module system but also externally towards other systems. Externally exposed interfaces belong to the module system's external Application Program Interface (API). They should be carefully designed since changes in APIs will impact other applications. There are plenty of APIs freely available today for cloud services, for example, SkyScanner API (to build your own travel app) or Open Weather API (to build your own weather app). If any of these services suddenly change their API, many apps across the globe will be broken, generating a lot of frustration and extra work. To have a stable modular software system, careful design and governance of interfaces must also be implemented for interfaces between modules for internal use.
The intent of software modularity is different depending on the strategic targets of the software author. Here are some examples of strategy and intent:
In software, the term Module has a wide range of different definitions, much like the term Component. Even though it is a term with many different definitions, there are commonalities in the descriptions. Let's have a look at some of these descriptions.
Starting with:
A module is a piece of code that can be independently created and maintained to be (re)used in different systems.
and Wikipedia describes modular programming as:
"Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules …"
Which are the commonalities?
A software module is independent of other modules in the sense that it is possible to develop and maintain a module with minimal to no impact on other modules. It does not mean that a module has no dependencies on other modules when running the program.
This autonomy is an important aspect of a software module because it helps to increase productivity. Independent modules enable engineering teams to be independent of each other when creating, maintaining, and testing the code.
A module can be reused in different systems, and it is also interchangeable (replaceable) within a system. Reusing modules in different systems or products without modification is very beneficial and will help shorten the time to market.
Interchangeable means you can replace a module without impacting the rest of the system. This flexibility is essential when upgrading a system because of new features or bug corrections. If you can limit changes to one or a few modules, less time is needed to test and implement changes. More frequent and smaller releases, in terms of impacted parts of the system, enable agility. Smaller releases also mean that you take less risk when releasing new features.
A module is a part of a module system. The first description above defines the decomposition in terms of code and the second in terms of functionality. Is that a similarity or a difference?
- We would say both. It is about decomposing the system into smaller parts, but:
Decomposition in terms of code is about organizing the code where a module is a structural unit. Different programming languages support the software modularization concept but not in precisely the same way. For example, a Python module is a file, but a Java module is much more. A Java module consists of one or many packages (another structural unit) and a descriptor that defines the packages that are exported from the module and the other modules that it requires to work. It is only the exported packages that are accessible for other modules to use.
Separating functionality is about organizing logical functions into logical software modules. This organization is beneficial when specifying and documenting the architecture of a system. A logical module may be realized by a code module or another structural unit, like a package. In UML (Unified Modelling Language), a modular system can be described with a UML Component diagram.
There are some important properties of a software module that make it possible for teams to work independently, making the software module reusable in many systems and interchangeable.
A module…
encapsulates functionality and data. Encapsulation is about hiding the implementation details of a module. The less a module knows about other modules, the less dependent it will be on changes in other modules. Other modules can only access functionality and data via the provided interface. Generally, it is good to encapsulate as much as possible.
provides an interface to other modules for accessing its functionality and data. The software module interface should be as abstracted and as small as possible. Fewer details mean looser coupling between software modules and make them more independent, reusable, and interchangeable.
requires interfaces provided by other software modules. To realize the functionality of a software module, it must sometimes use the provided interfaces of other modules. A software module that uses another module through its interface has a dependency on that other module. The fewer dependencies, the better. Since non-backward compatible interface changes may occur in a software module's lifecycle, an update to a module can be forced without any benefit to customers, such as better performance, functionality, or quality. Forced software updates that do not improve customer benefit should be considered a cost of complexity in software development.
Let's illustrate.
A module has a provided interface, that other modules in the system can consume as well as a required interface, i.e. an interface that is required for the module to function correctly:
Figure 1. A software module provides and requires interfaces
In the example below we have 4 modules, A, B, C and D. Module B, with its Module Variant 1 provides an interface B to Module A and requires both Module C and Module D provided interfaces according to below.
Figure 2. Two software modules that provide and require the same interfaces are interchangeable
Assume we have a new Module B, Variant 2, with improved performance. If variant 2 provides the same interface and requires the same interfaces as variant 1, then it is interchangeable with Module B, Variant 1.
Figure 3. Two software modules that provide and require the same interfaces are interchangeable
A module that defines provided and required interfaces become reusable in other systems, e.g., Module B, Variant 1, can be reused in another system as long as the required interfaces are provided.
An often-overlooked aspect of forming software modules is company strategy. When creating a module with the properties described above, we typically have a specific intent in mind. This purpose should be explicitly decided and documented. The intent is expressed by answering strategic questions, such as:
As software architecture can easily be circumvented or misunderstood by the coders, it is vital to repeatedly look back at why certain functions were grouped into modules. For this reason, we believe it is crucial to state and document the strategic intent of a module. In fact, a defined module strategy should be considered a criterion to call something a module. A software module with a defined module strategy is a strategic software module.
Our colleague's blog post "What is a good modular system" explains that a modular system must be flexible for a large scope and live for a long time. Creating strategic software modules increases the chance of a longer lifetime, and robustness becomes less person-dependent.
Documenting a strategic software module is different from traditional software documentation. The strategic software module should encapsulate function, define interfaces, and be driven by strategy. This information needs to be documented to easily communicate, discuss, and explain. One way of doing it is to create a one-page strategic software module specification stored in your document management system. Another flexible way to document these aspects is a wiki.
Figure 4. Example of a Strategic Software Module Specification in a one-page slide
To enable efficiency, flexibility, and agility, large and complex systems must be decomposed into smaller parts or modules. Independent modules make the development teams more autonomous, resulting in improved efficiency and shorter time to market. A module is also reusable in different products. Companies with a modularized product portfolio build their products from a mix of common reusable modules.
By defining the strategic intent of a software module, you create a strategic software module. These modules will be more resilient to change since the reasons why the modules were formed are documented.
It is fascinating that a module with only three simple attributes - encapsulation, interfaces, and strategy – can deliver so much value.
If you want to read more about how to create a modular architecture using a proven method called the Modular Function Deployment you can download our 5-step guide here below:
If you are planning to improve your software architecture with, for instance, support for automatic Over-the-Air software updates (OTA) or introduce new innovative AI functions, it can be tempting to rewrite all the software from scratch with the latest tools and technologies that promise faster implementation speeds, higher innovation and easier maintenance in the future. This is true if the software you are trying to replace is very old or the functionality or technologies you aim to add is highly innovative.
While this may seem like a good idea on the drawing board, re-factoring what you have first into strategic software modules is a much safer and less costly way to go. If done correctly, you will reap the benefits of future technologies faster while keeping or improving the performance of the software you already have.
This blog digs deeper into why: Improve your Software Architecture by Code Refactoring, Not Rewriting.
Many companies are looking at Agile development methodologies to improve their ways of working and becoming better at adopting to new and changing market requirements.
Not only is modularity a key way to achieve these benefits for both software and also hardware, but it can also be used to address difficult development resource shortages.
If you are able to pro-actively modularize an old monolithic software system, using the previously mentioned re-factoring techniques, it could potentially prepare the development organization to a world where the software platform can be migrated to never and more powerful hardware without a massive workload and hard deadlines. It could also be used to support 2nd sourcing critical hardware components that the software relies on, improving platform resilience and potentially lowering purchasing costs.
The blog From a Hardware-First to a Software-First Business will explain in more details how this can be done.
Software Modularity is a passion of ours and we are happy to continue the conversation with you. Contact us directly via email or on LinkedIn if you'd like to discuss the topic covered or be your sounding board in general around Modularity and Strategic Product Architectures.