Showing posts with label continuous delivery. Show all posts
Showing posts with label continuous delivery. Show all posts

Sunday, 27 April 2014

Microservices relax

Recently I blogged explaining that I view microservice architectures as a collection of strategies to independently vary system characteristics. I suggested that these strategies could be framed in terms of a generic architectural constraint:
X can be varied independently of the rest of the system.
Mark Baker pointed out that while I employed the language of architectural constraints, my one "isn't upon components, connectors, and data." He referred me to Roy Fielding's excellent thesis, famous for defining the REST architectural style, for a rigorous description of how architectural constraints can be described.

Thinking about the problem further, I considered what kind of data flows through the microservice systems I've worked with. I realised that many of the qualities that characterise a microservice architecture are not visible during a single system run. Microservice architecture can only be explained in terms of components, connectors and data if the constituent services are themselves regarded as data, and the processes that evolve them as components and connectors.

I don't think that's too much of a stretch. For systems that are deployed via continuous delivery pipelines, the automated deployment infrastructure is part of the system itself. If the build is red, or otherwise unavailable, then the production system loses one of its most important capabilities - to evolve. The manner in which the code/data that specifies the behaviour of the system evolves can be subject to similar constraints to the introduction of novelty into conventional system data.

Viewed that way, it becomes apparent that the constraint I proposed was the inverse of what it should have been, namely:
X's variation must be synchronised with the rest of the system.
Monolithic architectures are subject to this constraint for various values of 'X'. Microservice architectures are produced via the relaxation of this constraint along different axes.

The process of starting with a highly constrained system and gradually relaxing constraints that it is subject to is the opposite of the approach Fielding advocates in his thesis. When deriving REST, Fielding starts with the null style and layers on six constraints to cumulatively define the style.

However, the microservice style is a reaction against highly-constrained monolithic architectures, so it has taken the opposite approach, which is to peel away constraints layer by layer in order to introduce new flexibility into the system.

For example, a monolithic system might consist of five functional areas, all integrated within a single codebase. For a functional change to make its away to production, the data describing the system's behaviour (its source code) is modified, checked-in and moves through the deployment pipeline into production. This must happen for all five functional areas as one, because the transaction of deployment encompasses all five pieces of data.

This system is devolved into a system of five microservices, each living in an independent source control root. A change to any one of those services can be checked in and move through its pipeline to production independently of the others. The deployment transactions are now smaller in scope, encompassing only a single service at a time.

The change in the scope of a single deployment generates options for the maintainers of the system. They can now release changes to one of the five functional areas without downtime to any of the other four.

But, as is the case with real options, this comes at a price. If the five areas interact, their APIs need to be versioned and kept backwards compatible. Changes that crosscut multiple services need to be carefully orchestrated to avoid breaking changes, whereas in the original monolithic system such refactorings might have been made with impunity.

Generally speaking, for each constraint that is relaxed in a microservice architecture, there is a corresponding real option generated and a corresponding coordination cost incurred. For good explanations on real options and how they apply to software development, see the various works of Chris Matts, including the book he wrote with Olav MaassenCommitment.

I think that it's a productive approach to describe microservice architectures in terms of the the relaxation of architectural constraints relative to a monolithic architecture. This provides us with a model not only to analyse the runtime properties of the system, but also its evolution and the options it affords its maintainers.

Friday, 17 August 2012

It's all production

Every now and then, I come across a discussion about whether test code deserves as much care as production code. I understand what is meant (the answer is yes), but I don't accept the premise of the question.

All code is production code. Deployment scripts, tests, database migrations and Java controllers all play a part in delivering value to the users. If a piece of code really has no effect on production, why was it ever written?

Monday, 14 November 2011

Continuous receipt - sacrificing versions

Last week I received an email that convinced me that the way we think about versioning has irrevocably
changed. Here is the meat of the mail:
IntelliJ's Perforce plugin now has job support.
While this is a valuable feature for me in my current project, it's hardly a major event for software in general.

What struck me was the author's implicit assumption that IntelliJ is a single continuous entity that changes state. IntelliJ "now" behaves differently to what it did a month ago.

To a user, "IntelliJ" is becoming less a description of an immutable executable than the name of an evolving organism of features. Whereas once we spoke of the 2010 incarnation of a product verses the 2011 product, soon we will speak of how a piece of software behaved in 2012 compared to 2013.

Web applications like Facebook, Twitter and Gmail have been doing this for some time. It's becoming the norm for desktop apps too.

The frantic pace of continuously delivered versions is obliterating the end-user's concept of a version altogether. Where previously we expected to pull new features by explicitly choosing to upgrade, we now accept that our software will frequently be pushed changes - almost in real time.

This large number of minutely differing versions is similar to how animation generates the illusion of motion. The more frequent the changes, the smoother the effect. As video games have increased their frame-rates they have made older games look clunky and awkward by comparison. Publishing games with 1995's industry standard frame-rate would put a studio at a serious competitive disadvantage today.

Developers who are unable to embrace the concepts of continuous delivery will find users perceive their software in much the same way.