pixel - Fotolia
When it comes to application architecture, the main topic revolves around monoliths and microservices. But for operating systems, there is a third approach called the microkernel.
A microkernel architecture is called a plugin architecture because of the way capabilities and functionality are added to a minimal core OS. They're an efficient way to achieve application customization and can offer software lifecycle benefits.
Find out how a microkernel architecture pattern provides the best of both the monolithic and distributed microservices approach to application development and management.
What is a microkernel?
Microkernels arguably fall between a microservices-based architecture and a monolithic one -- a microkernel contains only the required amount of software to implement an OS.
A monolithic architecture is easy to build because all the pieces are together. However, it must be tested as a single unit, which makes debugging and updates potentially painful. Microservices are the opposite. They are easy to debug, isolate and deploy, but there are many moving parts to manage. Tracking the interactions between components can be challenging.
With a microkernel architecture, there is a core and plugins. The core application is centralized, like a monolith. And most additional development is done through plugins that add capabilities or modify existing functionality. Generally, these plugins do not know about each other and do not communicate with each other. However, the microkernel provides interprocess communication -- a way for the processes to talk.
Good places for a microkernel
Consider a microkernel architecture when you have a base application that uses bolted-on features and skins, or one that must be customized for clients. For example, a base accounting application could offer premium extensions. Many ERP applications already welcome extensions and operate in an entire third-party ecosystem.
If your application needs extensions, or you are trying to make a monolith's code independently testable, then consider the microkernel architecture.
Common microkernel plugins
Most software users are familiar with plugins. Products like Firefox, Chrome and WordPress have plugins and extensions that override basic capabilities or add new ones. A plugin can be as simple as a program that locates coupon codes, or as complex as record-and-playback test assistants, like Selenium IDE.
Even popular Java-based application editors like the Eclipse IDE use plugins. I use JUnit unit tester and the Vim text editor plugins to embed checking loops into code and speed up editing processes. There are also extensions that highlight syntax and auto-complete in nearly every language.
At the code level, one way to implement plugins is with the strategy pattern. This is a behavioral software design pattern that can select an algorithm at runtime. For example, an insurance application must process taxes in different ways in accordance with each state's laws. A monolithic application architecture would use a complex set of nested if statements. A microkernel architecture would use 50 different objects -- one per U.S. state -- that all inherit from a base class called state_tax. Developers can create the appropriate tax object for each state, then pass the record to whatever object they have created and call the ->process() method.
From a monolith to a microkernel
Developers need to break an application down into isolated components for testing. With microservices, that means standing up a server and connecting it to a test database. With the microkernel approach, we can add a mechanism within the application that isolates and runs arbitrary code.
In languages like Ruby and Python, for example, the application can read code from a file, convert the code into a string and execute it using an eval method. Here's a simple example of code that can be read from a disk:
calc = "1+5";
result = eval(calc);
This code is overly simplistic -- it poses potential security gaps, doesn't address memory limits and doesn't handle inter-process communication or parallel processing. It exists simply as an example. A true plugin approach would likely use fork() or threads to handle multiple plugins working at the same time on the microkernel.
The example code highlights the potential value of plugins. The example above runs in the same memory address space as the core application. It has the power to change class definitions, or to create a new class that inherits from the old class and replaces the variables.
Other languages use tools like reflection, anonymous functions and code interpolation. Some even embed code from different languages. For example, a tool may cross-compile multiple .NET languages down to one common language runtime.