Favor Feature Toggles over Feature Branches

As you may be aware, our development process at Pluralsight is a kanban style of agile. We limit our work in progress so that we can maximize the flow of new features into production. When you combine this with our focus on automated testing, use of a continuous integration server, a distributed source control system, and single click deploy/rollback, the result is continuous delivery. Even with a fairly small team, we almost always deploy new features more than once a week and occasionally two or three times in a single day.

Because of this style of development, we occasionally saw the Big Scary Merge described by Martin Fowler. As a team, we value continuous improvement, so we researched ways to address problems of merging when working on feature branches. So despite some skepticism, we have been experimenting with feature toggles. Many developers are familiar with the term, but there are few examples of how it is done, so allow me to share how we do it in our ASP.NET MVC web site.

How we do it

First of all, we follow Martin Fowler's advice and toggle close to the user interface. In the following sample, you can see that there is a Change User Name feature that can be toggled on and off. The view model we pass in has a property that will cause the change user name partial view to be shown only when the feature is on.

@if (Model.ShowChangeUserNameOption)
  @Html.Partial(MVC.Profile.Views._ChangeUserNameVm, Model.UserNameVm)

Now, this view model property is set by the view model builder in the application layer of our web app. As you can see, it is set using the value from the settings provider which reads directly from the web.config.

EditUserProfileVm BuildEditUserProfileVm(UserAccount userAccount)
  if (userAccount == null) return null;
  return new EditUserProfileVm
               BasicInfo = BuildEditBasicUserProfileVm(userAccount),
               EMailInfo = BuildChangeUserEmailVm(userAccount),
               ProfileBelongsToCurrentUser = userAccount.Handle == currentUserProvider.UserHandle,
               UsageInfo = userProfileUsageInfoVmBuilder.BuildUsageInfo(userAccount.Handle),
               ShowIndividualUpsellOffer = ShowIndividualUpsellOffer(userAccount),
               ShowCorporateUpsellOffer = ShowCorporateUpsellOffer(userAccount),
               ShowChangeUserNameOption = settingsProvider.FeatureToggleUserNameCustomizationActive

There isn't much of interest here in the settings provider other that the fact that we default the toggles to off, so no new features accidentally slip into production.

public bool FeatureToggleUserNameCustomizationActive
  get { return GetOptionalBooleanSettingWithDefaultValueOfFalse(SettingKeyNames.FeatureToggleUserNameCustomization); }

By treating the feature toggles as a first class member of the application, we can easily write unit tests to verify the behavior of the code when the feature is active and inactive. We can easily work with the new feature locally by adding a single appSetting to our local web.config files.

<add key="FeatureToggleUserNameCustomization" value="true" />

We can release our code even if this feature isn't complete because no one can access it until it is enabled. Additionally, we can deactivate it in production very easily should we discover a problem.

What we learned

During our last team retrospective, we discussed our experience with feature toggles and feature branches. After reviewing what we saw as the pros and cons of each, we decided that we favor feature toggles over feature branches. We will still use feature branches when appropriate, of course. Also, this preference does not affect the work flows of individual developers which may involve local branching.

Feature Branches

  • Pros
    • Code for a new feature cannot possibly affect production because it hasn't been deployed there
    • You can work on a feature without being concerned for how the development of other features is progressing 
    • Our continuous integration server is aware of branches and builds them automatically
    • Our distributed version control system is designed to make branching and merging painless
  • Cons
    • The Big Scary Merge is still painful despite tool support for branching
    • There is a chilling effect on refactoring

Feature Toggles

  • Pros
    • We avoid the Big Scary Merge
    • We have to address upgrade paths and testing as we develop new features rather than after they are complete
    • We integrate all in-progress features as they are developed so there are no surprises when we put them together
  • Cons
    • There is a possibility that incomplete features could negatively impact production
    • Though we haven't seen this, there could be reluctance to push to the shared repo


Popular posts from this blog

Architecture at different levels of abstraction

TFS to SVN Conversion with History