Microservices Until Macro Complexity
At QCon New York last month I hosted a panel on architecture and nearly all of the questions were about microservices. It isn’t hard to sense the excitement many are feeling about this approach. When I first heard about microservices, the people talking about them framed them as a reaction to monolithic architecture, frameworks, and SOA. It was back to basics - concentration on something that adept teams could build from the ground up.
One of the things that I found very appealing about microservice architecture was the accommodation of human scale. Microservices are small and focussed by design - created by no more than a handful of people. It’s a level of granularity we often miss in programming, or have no real way of enforcing.
It is going to be interesting to see how this approach scales. Some organizations have a relatively low number of microservices. Others are pushing higher, around the 600 mark. This is a bit beyond the point where people start seeking a bigger picture. If services are often bigger than classes in OO, then the next thing to look for is a level above microservices that provides a more abstract view of an architecture. People are struggling with that right now and it was foreseeable. Along with that concern, we have the general issue of dealing with asynchrony and communication patterns between services. I strongly believe that there is a law of conservation of complexity in software. When we break up big things into small pieces we invariably push the complexity to their interaction.
Back in the 1990s, I used Microsoft COM a bit. Microsoft touted it as an improvement on OO that solved what was known as the fragile-base class problem. One of MS’s big headaches in that era was how do incremental update of applications (think Microsoft Office) before the internet deployment era. COM was a binary interface standard that was based, essentially, on C++ style vtables with that always contained three mandatory functions: QueryInterface, AddRef, and Release. You could query a black box for an interface for a component and use if if you found it. The trick, for developers, was to come up with a design for a set of components, design the COM interfaces that could be used to find and interact with them, and do all of the manual reference counting correctly in order to avoid memory leaks and random crashes. It was tough. Definitely not as easy as writing classes in an OO language. But, people did do some very cool things in COM and its successor DCOM, it’s just that they were never very complex because you had to fight so hard to get something simple to work.
I feel that micro service architecture is at that point today. Few organizations have pushed it hard enough to see the challenges that appear at scale. There’s a a bit of overhead involved in implementing each microservice. If they ever become as easy to create as classes, people will have a freer hand to create trouble - hulking monoliths at a different scale. Personally, I hope we don’t get to that point any time soon. Having an approach that is hard to put into practice can be decent bound on complexity. And, don’t we need that, really?