Git came on the scene with a great story about the power of branches. Those of us who worked with other source code management throughout the years mostly acquired a fear of branching in source code. With git – everyone discovered branches were free, cheap and easy. You could have long or short-lived branches, cherry-pick between them – that felt like a superpower – and, of course, pull requests came along and changed the daily workflow of developers forever.
One of the lessons that software borrowed from manufacturing is the idea that too much inventory is bad – inventory is stuff that costs money sitting around, adding no value for anyone. Continuous delivery practices tell us that software that is not deployed is also inventory, so it is best to get it deployed – ideally in small pieces as they become available – as soon as practical. If you read the State of DevOps report from DORA, you can see many other benefits to this practice; benefits that are real in human and financial terms.
However, with easy and cheap source code, branching it is all too easy to accidentally build up this inventory of unused or undeployed code. Getting code into the main line/master/trunk sooner and shipped is a good idea.
So what are some ways to pare back this inventory? We want to think a bit about how we structure code, and also how to decoupled the release of a feature with the physical deployment of the changed code. Let’s talk about these:
- Branch by abstraction instead of feature branches
- Feature flags/feature management
Branch By Abstraction
Branch by abstraction can be viewed as the counterpoint to using feature branches in source code. Feature branches are a powerful technique I am sure has been used anyone who has taken advantage of git. We have all probably scribbled branching strategies on whiteboards that look like something as described on this page:
Image credit: Better Explained
There are many tools for git that will help you visualize this as you need it. However, over time I felt like I looked like this when I was explaining this stuff in front of a whiteboard:
Just to be clear – this is not good.
Branch by abstraction, however, has nothing to do with making branches in git, and as a concept has been around for a while. The first time I saw it was in this excellent talk on Android development by Jesse Wilson.
Say you needed to add a new item to a sidebar on a web app, or you need to add support for some new form of authentication. In branch by abstraction, you would have a high-level API to show what is in the sidebar, or you would have an interface that abstracts away the authentication mechanism. You then add in the new code behind a flag that turns on the feature when it is ready to be used. You don’t keep this source code on a branch, ready to be merged later, or cherry-picked, but it is in the master branch as soon as possible. The branching is basically fancy if statements deciding if it should show the sidebar. You branch in execution, not in git.
What I described above is mostly just good practice – abstractions are good right? The extra tweak is the use of a feature flag. I really can’t say it better than the above-linked video:
There are so many advantages on top of keeping your inventory light – the master is always shippable, and you can conduct experiments or controlled releases of a feature. Just because it is in the master branch doesn’t mean people have to use it. That brings us to…
Feature Management and Feature Flags
With feature management, you allow the release of software to users to be a business decision instead of a technical decision. In this case, I wanted to highlight CloudBees Rollout, which is a feature flag service. Of course, there are other ways: you can use service meshes if you are building web apps on a platform like Kubernetes, or roll your own feature flags system in your own way.
A feature flag service like Rollout provides the backing store and API that your branching source code uses to decide to offer that new form of authentication, or show that new feature on the sidebar.
It may make decisions on what segment of users see a feature – this could be for business purposes (perhaps you have regional launches) – or perhaps it is a higher risk feature, and people want to watch their monitoring systems to see if there is a spike in problems as the feature is rolled out.
The features being managed don’t have to be on or off either – there can be a branch selected based on a value, which is controlled by the feature management console. Remember, this isn’t a branch of source code, but a branch of execution.
If you still aren’t convinced, I recommend watching the talk. I also found this article on migrating a persistence, which is the oldest reference to branch by abstraction I could find, and it is still a great read.