Feature switching: a better way to collaborate

DZone 's Guide to

Feature switching: a better way to collaborate

· ·
Free Resource

One of the biggest pitfalls on working in teams where branches are created to work on features is that we are not continually checking in to the head revision / trunk. This means our work is not constantly being integrated. The feature may be small and we can integrate back in a day or 2 but there are a lot of instances where the feature is longer (2 – 3 months). If this is the case we need to be continually merging and then re-branching. This means we are going through merge issues more often than required.

What if I was to tell you there was a much better way? I bet you would be a little sceptical at first but then see the benefits of it. When developing features, we can all work from the trunk by feature switching. Feature switching (FS)is the use of a configuration system, db or config file, where we can turn a feature on or off. This will help us with canary releasing (releasing features to just a small group of users) & A/B testing. We really start to see how useful FS is when we look at moving towards a continuous delivery workflow.

We can write ‘feature’ code to the trunk and enable a switch to turn it off and then push to our head revision. We can deploy our system as the code we have written will not be parsed or shown (if it is front end changes). The danger is that we can forget to disable the feature. I usually setup my web.config transformations to take care of that issue.

FS can be temporary, while a small feature is being built. IF this is the case when the feature is complete and signed off then we must remove all instances of the switching code and the settings to go with them. FS can also be long term, e.g. being able to disable the registrations to an event on a website. It is important to keep temporary and permanent switches separate for clarity.

This code shows that on a simple request to the register action, then a view will be returned. What if we wanted to start tinkering with the view? What if we wanted to start adding new fields to the registration form but not show it until the feature is finished? Well I'm sure some would say create a cpy of the view and work from that - but there are no ways to get to that view as it is not returned from a request.

This is the same action method with some further logic added to it. This effectively checked to see if a feature is actually enabled and if so the new version of the View is rendered. Otherwise the old version of the view is rendered. This is a very very simple demonstration of feature switching. I would try not to do it this way – ‘newing up’ the FeatureManager inside the action method. I’d use Dependency Injection to inject an instance into the constructor for loosely coupled code.

What if I wanted to do this as part of a View and not have to modify the code at all. We can look at the following example:

This example says that if the feature is enabled then show the new panel. This uses a Html Helper method to hide the logic of the switch. All I have to do is to pass the name of the feature to the helper. The helper code is as follows:

Pretty simple and straightforward stuff. Using this type of approach will mean we can all work effectively on the head revision which will save us time (we shouldn't have problem merges). This will als let the CI system take care of integration and spotting integration issues earlier. It will also mean that when we check into the trunk our application should be in a deliverable state. There are much more complex ways to feature switch. We will cover those in a later post.

I have taken a copy of the ASP.NET MVC MusicStore and added some feature switches to it. This is available on my github repository. Please feel free to take a copy and have a play with the switches. The code there is what is contained in this post


Published at DZone with permission of Paul Stack , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}