Merge hell and Feature toggle
For about three years ago we use feature branches in our current project. It took about a half to one day to merge those branches before deployment. The reason why feature branches was used was more or less because most team members have worked like that in earlier projects and they thought it was the way to work. At that time some of them also wanted to introduce bug branches! That was the right branch strategies for them, because that was what they have learned.
We all are often stuck into a pattern of thinking, we have during our life learned from the community sounding us what is the correct way of thinking and doing stuffs. In school we learned that 1+1 is 2. We are often stuck into that pattern, so when someone ask us "what is 1+1", most of us will probably say two. But what If someone suddenly says, no it's three? Well, I think most of us will say NO, it isn't, it's two. 1+1 can actually be three. It's just three character, 1, + and 1, it's three. It's NOT strange that we do what we are used to, and it's absolutely nothing wrong with us because of that. About fourteen years ago I went to a course, "Physiology at the workplace" at the university. A teacher show us a picture of a cube. She said, only a child and a genius can take that cube apart.
No one in the classroom managed to take the cube apart. The teacher told us that we have during our life learned a pattern, which is why we didn't manage to take it apart. A child haven't learned it yet, and a genius is just a genius. What I learned from that day, is that there may be a way to solve problems, and even if we don't see it, it can be the pattern we have learned that is just in our way. But I know that we can find the elephant in the room, and slice it!
And in my team we almost did it when it come to the branch and merge hell! We started to do a research about how we could reduce the merges, how we could work with the source code, and how our process could help us reducing the waste.
At the moment we don't often need to merge at all. We haven't reach the ultimate goal yet, but we aren't far away from reaching it.
At the moment we work against one single branch during an iteration, but when we are done we create an UAT branch. UAT then turns into a Release branch before deployment to production. There are some problems with those branches. First we build from them. So when we do a UAT release we build the UAT branch and deploy the binaries. The problem with this is that you can't really trust the code in the UAT branch. From the time when the branch was created, changes to the code may happened. For example a hot fix in the UAT that someone forget to merge to the main branch etc. We even have experienced a hot fix made in the release branch, but was never merged into the main branch. What happened was a hot fix was release to production. But the next release introduce the bug again, it took few month until it was detected again.
During our progress to reach a great Continuous Delivery experience, we have started to apply feature toggle and branch by abstraction to eventually remove branches to just work against one single branch.
By using feature toggling, we can release unfinished code into production, we just make sure the code will never be executed. By doing so we can simply work in one singe branch, and can avoid merges between branches, we can also reduce the problem we had with hot fixes in other branches that wasn't merged. We can also continuous deliver completed feature into production that is not yet enabled, but can be enabled by the product owner when he feels it's time to enable it. If a bug of a new deployed feature is found and a critical fix need to done, it can be turned off in production.
How we use feature toggle
Something that is important when it comes to feature toggling is to remove the switch when the new feature should always be on. If we don't remove it we can easily introduce a technical debt. We wanted to make it easy for use to find and remove the switches from our code. So we introduced a class for each feature and added it to a specific folder.
public class MyFeature : ConfigSwitch
{
public bool IsEnabled()
{
//...
}
}
Note: The ConfigSwitch base class just help us to read from the application configuration file if the feature is on or off, we use <appSettings> to turn on and off a feature.
In our code where we want to use the new feature or the old one based on the feature is enable or not, we just use the class we have created:
var myFeature = new MyFeature();
if (!myFeature.IsEnabled())
{
//Old code
}
else
{
//New code
}
We also use the feature toggle when we register our dependencies. Because we work against abstractions we can easily replace the detail of the abstraction by another one. Here is our registration of dependencies:
if (!myFeature.IsEnabled())
container.Register<IMyFeature, MyFeatureV1>();
else
container.Register<IMyFeature, MyFeatureV2>();
The reason why we add a new class for the feature to turn on or off, is that we can simply remove the MyFeature class and easily find all places in the code where it was used, and just remove the if statement.
Summary
By using feature toggling we can work in one single branch, we can reduce merges and continue deliver from that single branch into production. It requires disciplined team members, for some this is a new way of thinking and working. It's not a Silver Bullet, it is as always a "it depends!". Some project it may not work, in others it would. Just don't let the elephant in the room fool you. Find it, and slice it!
If you want to know when I publish a new blog post, please feel free to follow me on twitter: @fredrikn