“The need for a common language requirement is the chief problem microservices solve.”
Part 6 – Episode IV: A New OOP
Our series exploring the six independent yet related threads that are converging to drive dramatic transformation in information technology is entering the home stretch today. I’ve been visiting each of these threads in turn, as shown in the diagram below. Each has been evolving on its own, rooted in decades of research, innovation, and trial-and-error. They are coming together in the second decade of the 21st century to revolutionize IT in ways the scope of which has not been seen since the 20th.
Today, the wheel turns to “microservices.”
Most definitions of microservices explain it as an architectural concept in which complex software systems are built from interconnected processes; the interconnection is typically facilitated by Internet Protocol transport and is “language agnostic.” As with everything else in the above wheel, microservices are nothing more than the natural evolution of software architecture as it changes to take advantage of the ubiquitous Internet in both senses of its geographic reach and the adoption of its core technologies.
I like to think of microservices as the natural evolution of Object Oriented Programming (OOP). OOP models software components as objects. Objects are typically instances of classes, a class simply being a pattern or blueprint from which instances are built. An object’s interface is the set of externally visible methods and attributes that other objects can use to interact with this object. A simple example is class
Point, which has attributes
Y to represent the point’s coordinates in a Cartesian plane, and methods such as
move() to alter those coordinates.
Classes are typically defined using languages such as Java. Indeed, most modern languages have an object concept, though their implementations differ. After defining the classes, one writes executable code to create object instances, and those instances themselves contain code in their various methods to interact with other objects: creating new objects, destroying them, invoking them to do work of some kind – all of which amount to a coordinated effort to solve a problem.
Class libraries are pre-written collections of classes that solve common problems. Most languages come with built-in libraries for things like basic data structures (generic queues, lists, trees, and hash maps). Open source and the Internet have created a rich but chaotic sea of class libraries for literally hundreds of different languages that solve even more specific problems, such as an e-commerce catalog or a discussion board for social media applications.
Until recently, if you wanted to build an application that used pre-built libraries from disparate sources, you chose a language in which there was available an implementation of each: The easy way (there are hard ways, of course) to have the code work together – to have objects from one library be able to see and use the interfaces of objects from the other libraries – was to use the facility of the underlying language’s invocation mechanism. The need for a common language requirement is the chief problem microservices solve.
A microservice is really nothing more than an object, the interface of which is available as a network addressable target (URL) and is not “written” in any specific language. The main difference is that the interface between these objects is the network, not a memory space such as a call stack or a heap.
Every interface needs two things to be successful: 1) marshaling, which is the packaging up and later unpacking of a payload of information, and 2) the transmission of that payload from object A to object B. Interfaces inside of an execution environment achieve both of these things by simply pointing to data in memory, and the programming language provides an abstraction to make sure this pointing is done safely and consistently.
Microservices are loosely coupled – they don’t share a memory space, so they can’t marshal and transmit data by simply pointing to it. Instead, the data has to be packaged up into a network packet and sent across the Internet to the receiver, where it is unpacked and used in a manner the caller expects. The Hypertext Transport Protocol (HTTP) is the ubiquitous standard defining connections and transfers of payloads across the World Wide Web, atop the global Internet. When used in a particular way that adheres to the semantics of web objects, HTTP can be used to implement RESTful interfaces. The definition of REST and why it is important is beyond the scope of this article, but there are good reasons to adhere to REST.
Even so, the use of the microservices model is exploding, and we’re seeing more hyper-reuse of code and services to build software. When “shopping” for a service, application developers typically follow this workflow:
- If a service already exists, we simply pay for it (if required) and knit it into our application.
- Else, we need to create an instance of the service, so we “construct” an instance on our favorite cloud provider by spawning a Docker container from an image from a Docker repository, like Docker Hub.
It’s a new age of software architecture. For the purposes of this article (and because it supports the contrived title), I’m going to call it the Fourth Age, and compare it to the previous three as shown in the diagram below. (This is a related but different concept than the familiar “programming language generations” concept.)
The First Age of Software Architecture was characterized by a lack of abstraction. Setting binary machine language aside as something only a masochist codes directly, assembly language provided a convenient shorthand, but very little else in the way of supporting problem solving. The Second Age added procedural languages and data structure abstractions; however, languages were designed with an emphasis on general purpose code execution, and not the support of best practices in creating and operating upon data structures. The Third Age was the OOP age, where languages evolved to support a more regimented, system-supported means of curating data within a program. However, those structures were limited to software written in a specific language; interfacing with foreign code was not addressed.
The Fourth Age is the ability to combine code drawn from multiple sources and languages to create a solution. Microservices are only the latest and most unifying attempt at doing so. Previous attempts include Microsoft’s “Common Object Model” and the Object Management Group’s Common Object Request Broker Architecture (CORBA). There are many others. The point is, until we saw things like HTTP/REST, Docker containers, cheap cloud hosting services, and freely available open source libraries like Docker Hub become common place, the Fourth Age couldn’t reach maturity – it was held back in many ways that microservices now have the opportunity to transcend.
So it is the age of the microservice, and the transformation of IT as we know it is reaching the peak of its powers. If train for this new era you will, clear your mind you must, and changes accept.
May the Fourth be with you.