Distributed big balls of mud

If you can't build a monolith, what makes you think microservices are the answer?

If you want evidence that the software development industry is susceptible to fashion, just go and take a look at all of the hype around microservices. It's everywhere! For some people microservices is "the next big thing", whereas for others it's simply a lightweight evolution of the big SOAP service-oriented architectures that we saw 10 years ago "done right". I do like a lot of what the current microservice architectures are doing, but it's by no means a silver bullet. Okay, I know that sounds obvious, but I think many people are jumping on them for the wrong reason.

From monoliths to microservices

I often show this slide in my conference talks, and I've blogged about this before, but basically there are different ways to build software systems. On the one side we have traditional monolithic systems, where everything is bundled up inside a single deployable unit. This is probably where most of the industry is. Caveats apply, but monoliths can be built quickly and are easy to deploy, but they provide limited agility because even tiny changes require a full redeployment. We also know that monoliths often end up looking like a big ball of mud because of the way that software often evolves over time. For example, many monolithic systems are built using a layered architecture, and it's relatively easy for layered architectures to be abused (e.g. skipping "around" a service to call the repository/data access layer directly).

On the other side we have service-based architectures, where a software system is made up of many separately deployable services. Again, caveats apply but, if done well, service-based architectures buy you a lot of flexibility and agility because each service can be developed, tested, deployed, scaled, upgraded and rewritten separately, especially if the services are decoupled via asynchronous messaging. The downside is increased complexity because your software system now has many more moving parts than a monolith. As Robert says, the complexity is still there, you're just moving it somewhere else.

There is, of course, a mid-ground here. We can build monolithic systems that are made up of in-process components, each of which has an explicit well-defined interface and set of responsibilities. This is old-school component-based design that talks about high cohesion and low coupling, but I usually sense some hesitation when I talk about it. And this seems odd to me. Before I explain why, let me quote something from a blog post that I read earlier this morning about the rationale behind a team adopting a microservices approach.

When we started building Karma, we decided to split the project into two main parts: the backend API, and the frontend application. The backend is responsible for handling orders from the store, usage accounting, user management, device management and so forth, while the frontend offers a dashboard for users which accesses this API. Along the way we noticed that if the whole backend API is monolithic it doesn't work very well because everything gets entangled.

The blog post also mentions scaling, versioning and multiple languages/frameworks as other reasons to choose microservices. Again, there are no silver bullets here, everything is a trade-off. Anyway, "everything getting entangled" is not a reason to switch from monoliths to microservices. If you're building a monolithic system and it's turning into a big ball of mud, perhaps you should consider whether you're taking enough care of your software architecture. Do you really understand what the core structural abstractions are in your software? Are their interfaces and responsibilities clear too? If not, why do you think moving to a microservices architecture will help? Sure, the physical separation of services will force you to not take some shortcuts, but you can achieve the same separation between components in a monolith. A little design thinking and an architecturally-evident coding style will help to achieve this without the baggage of going distributed.

Many of the teams I've spoken to are building monolithic systems and don't want to look at component-based design. The mid-ground seems to be a hard-sell. I ran a software architecture sketching workshop with a team earlier this year where we diagrammed one of their software systems. The diagram started as a strictly layered architecture (presentation, business services, data access) with all arrows pointing downwards and each layer only ever calling the layer directly beneath it. The code told a different story though and the eventual diagram didn't look so neat anymore. We discussed how adopting a package by component approach could fix some of these problems, but the response was, "meh, we like building software using layers".

It seems as if teams are jumping on microservices because they're sexy, but the design thinking and decomposition strategy required to create a good microservices architecture are the same as those needed to create a well structured monolith. If teams find it hard to create a well structured monolith, I don't rate their chances of creating a well structured microservices architecture. As Michael Feathers recently said, "There's 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.". I agree. A world of distributed big balls of mud worries me.



Re: Distributed big balls of mud

I agree, that if you don´t master software development without µServices, they won´t salvage your project.

µServices are just a means to an end. But which? Evolvability. Or sustainable software production.

But are they the only means to accomplish this? Or just the latest fad?

I think, µServices need to be put into perspective. What are they? What´s their category? I call that "container".

µServices contain code. They are a design time artifact for building evolvability into software. Other containers are (in increasing size): functions, classes, libraries, components.

But containers don´t just differ in size/granularity, I´d say. They also differ in how strong they encapsulate the implementation details of the code they contain.

Libraries are opaque containers. No source code/implementation visible, just an API. Components are libraries too, but separate the API (contract) from the implementation; thus clients of a component can be coded in parallel with the component implementation. They just need the contract. This enables a kind of "industrial" software development. Division of labor becomes easier.

And then, the next level of container granularity is µServices. They go beyond components in that they require a platform neutral contract - which accidentally entails they run in their own process. And thus you can write them using different platforms.

That´s it in my view. Nothing more, nothing less to µServices. They are just another type of container. So as long as you have difficulties structuring your software using the "lower level" containers like components, libraries, classes, functions... you won´t be able to reap many benefits from µServices. Where there are monoliths today, where there is no experience with components, µServices will actually make things worse, I guess.

Re: Distributed big balls of mud

I'm a fan of microservice architecture, perhaps because I find it natural. It is little more than a rebranding of a type of the simple componentised/service-oriented architectures we've been doing for a while but that doesn't detract from its utility any more than every UI framework throwing "MVC" about makes that pattern less useful.

When a team chooses microservices I think it's important to acknowledge they have at least made a choice. This alone might be the reason their project turns out better than a more de facto monolithic design. For this reason I think it's important to have "trendy" topics so that they can get teams talking about what they're doing.

You could throw Spring, Git, functional programming and just about everything else into the same bucket of hype but I'd still recommend (at least one of) them.

Re: Distributed big balls of mud

Interesting that Adrian Cockcroft says / believes that monolith is a great way to start app dev, and that microservices really add value once the system, dev team, customers scale. Of course that leaves a large chasm in between... http://www.infoq.com/interviews/adrian-cockcroft-microservices-devops

Re: Distributed big balls of mud

Yep, the second you introduce distributed, you need to leverage infrastructure that addresses network latency, fault tolerance, message serialization, unreliable networks, asynchronicity, versioning, varying loads within the application tiers etc. etc. Otherwise you're coding it yourself, a la NetFlix OSS and I suspect that is one of the main reasons for monolithic shops not being interested. Takes top level talent at the moment, not something all enterprises have access to. I can't see how a microservice would ever be as easy to create as a class, too many human-based design decisions involved, but I do share your concern that are plenty of traps to fall into. I do agree and that monotlithic applications designed in a certain way would reap some of the microservice benefit, but monolithic would never be able to be as testable, refactorable, approachable to a new developer, or as friendly when scaling the team. I think your blog on layer vs component design (an an architecturally evident coding style) provides a very balanced view of this, particularly w.r.t testability. Lastly - In some cases, monolithic containers are optimized for a single app or binary deployment unit, but often they must host a variety to achieve density or respond to business pressure to leverage expensive investment(s). Using microservice approach you can tweak each container for the purpose and context at hand. As vendors start to provide some of this "missing" infrastructure, devs will naturally be more free to concentrate on the design decisions inherent in distributed systems and will be less prone to err.

Re: Distributed big balls of mud

When we were building CORBA systems in the 90's, we talked about a lot of the same benefits as the Micro-services folks are now. Then the industry seemed to cool on distributed objects, even Martin Fowler declaring "Don't distribute your objects", mostly because of latency. Wondering why distributed Micro-services are good, but distributed objects are bad?

Re: Distributed big balls of mud

I was just getting started with Java/EJB in those days but here's a few things I can think of that have changed, making the design pattern more viable today 1.) advent of PaaS/Virtualization, making it easier to provision and operate on tightly bound code-to-container-to-OS environments - that wasn't around in CORBA days 2.) faster network in general, at least within data centers 3.) better caching technology, messaging technology 4.) simpler, more universal wire protocols like REST/HTTP

Add a comment Send a TrackBack