Modules
Some languages provide their own modular decomposition techniques that go
beyond simple libraries. They allow some lifecycle management of the modules, such
that they can be deployed into a running process, allowing you to make changes
without taking the whole process down.
The Open Source Gateway Initiative (OSGI) is worth calling out as one technology-
specific approach to modular decomposition. Java itself doesn’t have a true concept of
modules, and we’ll have to wait at least until Java 9 to see this added to the language.
OSGI, which emerged as a framework to allow plug-ins to be installed in the Eclipse
Java IDE, is now used as a way to retrofit a module concept in Java via a library.
The problem with OSGI is that it is trying to enforce things like module lifecycle
management without enough support in the language itself. This results in more
work having to be done by module authors to deliver on proper module isolation.
Within a process boundary, it is also much easier to fall into the trap of making mod‐
ules overly coupled to each other, causing all sorts of problems. My own experience
with OSGI, which is matched by that of colleagues in the industry, is that even with
good teams it is easy for OSGI to become a much bigger source of complexity than its
benefits warrant.
Erlang follows a different approach, in which modules are baked into the language
runtime. Thus, Erlang is a very mature approach to modular decomposition. Erlang
modules can be stopped, restarted, and upgraded without issue. Erlang even supports
running more than one version of the module at a given time, allowing for more
graceful module upgrading.
The capabilities of Erlang’s modules are impressive indeed, but even if we are lucky
enough to use a platform with these capabilities, we still have the same shortcomings
as we do with normal shared libraries. We are strictly limited in our ability to use new
technologies, limited in how we can scale independently, can drift toward integration
techniques that are overly coupling, and lack seams for architectural safety measures.
There is one final observation worth sharing. Technically, it should be possible to cre‐
ate well-factored, independent modules within a single monolithic process. And yet
we rarely see this happen. The modules themselves soon become tightly coupled with
the rest of the code, surrendering one of their key benefits. Having a process bound‐
ary separation does enforce clean hygiene in this respect (or at least makes it harder
to do the wrong thing!). I wouldn’t suggest that this should be the main driver for
process separation, of course, but it is interesting that the promises of modular sepa‐
ration within process boundaries rarely deliver in the real world.
So while modular decomposition within a process boundary may be something you
want to do as well as decomposing your system into services, by itself it won’t help
10 | Chapter 1: Microservices