Sunday, 22 July 2012

Simple database driven feature toggles for ASP.NET MVC


A bit like a broken record I keep mentioning that we use continuous integration at work. So blah blah blah, we need feature toggles. My previous experience has involved using a very simple feature toggling mechanism and looking into a few other open source feature toggling tools. For this blog I'm going to ramble on about another simple idea that I implemented using toggles stored in a database. This solution is specific to ASP.NET MVC due to the way the toggles are populated but I imagine similar mechanisms exist in other frameworks. Although I wrote most of the code, I can't take credit for the idea. That goes to a couple of my colleagues (see their blogs here and here). They each claim it was their idea. I'll let them fight it out. 

How it works

The feature toggles are stored in a static class. What? A static class?!? I don't like it! Bear with me. I thought the same when I first heard the idea but I was convinced otherwise. This static class is used purely to store the values of the toggles, that's it. This comes with a few significant benefits. Primarily it can be defined in a common project (our solution has a lot of projects) and then be used anywhere, view, service, or controller. In addition it doesn't need to be passed around via constructor injection so it doesn't pollute a huge number of classes in the code base. Just to highlight that point, there is absolutely zero IoC setup required to use toggles once the initial implementation is done. But wait, there's more good stuff. What about unit tests? Will adding feature toggles break them? Nope. Because the static class is just a container the toggles will default to being off. If you want to create unit tests which test the toggle being on, just set the toggle to true in the unit test. Easy.

So how is it populated? It's very simple. A new Action Filter is applied to all controllers. For our code this is very easy because all controllers inherit from a base class. On every page load this Action Filter retrieves the toggle values from the database, if they have changed. 

Why get toggles from the database? There are a few good reasons. Firstly it's very easy to change their value at run time. Secondly it's very easy to make them available to every project in a solution. This is in contrast to a previous mechanism I tried whereby the toggles were stored in appSettings in a web.config file which required the adding of a file attribute to the appSettings element in each project where the toggles were required. Another benefit of using database toggles is that the implementation can easily be extended. It would be fairly easy to add new features like toggles controlled by date or toggle state. E.g. Always on, always off.

Are there any disadvantages to this approach? Currently because the toggles are populated by an Action Filter they can only be used in MVC applications, not windows services or console applications etc. 

The code

FeatureToggles static class


Each feature toggle is simply a public static boolean with a private setter. Why a private setter? It indicates to others using that class that they shouldn't change the value of an individual toggle variable. However there does need to be a mechanism for setting toggle values for unit testing purposes, which is done by SetToggleValue. Reflection is used to prevent the need for any extra code being written when a toggle is added.

SetFeatureToggles is used to populate all the toggles using reflection. Again reflection means no code changes are required when adding or removing toggle variables. The toggle name passed in must match the name of the toggle variable. Note, the FeatureToggle classes passed into the method simply contain two properties, string Name and bool IsActive.

GetActiveFeatureTogglesAsStringForBodyTag returns a string containing a space separated list of toggle variable names prefixed with "FT_" which is outputted in the class attribute of the body tag in each page. This allows CSS rules to be defined for when the toggle is on.

HasBeenInitalised is required to ensure the toggle values are retrieved from the database the first time the application is run. This is a quirk of our implementation because the cache isn't necessarily invalidated when the application is restarted.

Action Filter


The job of this Action Filter is very straight forward. If the toggles have changed retrieve the values from the database and repopulate the static toggle variables. This avoids reloading the toggles on every page load. I'm not showing the implementation details of FeatureToggleService because it's very specific to our application. There's nothing special going on to be honest. GetAll() simply returns a list of FeatureToggle classes either from the cache, if populated, or the database. The FeatureToggle class has two properties, string Name and bool IsActive. HaveValuesChanged() unsurprisingly returns a bool indicating whether the toggle values have changed.

How to add a toggle

To start using a feature toggle only one step is required. Add a public static boolean property to FeatureToggles class.


Obviously the toggle will always be false until you also add the toggle to the database. This is done using a simple admin tool which can add, remove or flip toggles. Whenever one of these actions is taken the cache is cleared which will cause the static toggle values to be refreshed.

How to use a toggle

In code


In views

Programmatically hide or show a feature:


Or use the outputted CSS class:

Advantages/disadvantages

Advantages
  • Incredibly easy to add a new toggle
  • Incredibly easy to use a toggle in any layer of the application
  • Easy to extend the implementation. E.g. Add date after which toggle is active
  • Existing unit tests are not broken 
  • Toggles can be flipped easily at run time with no need to manually edit a config file
  • No IoC set up required
  • Toggles can incorporate CSS

Disadvantages
  • Only works in MVC projects
  • Some people won't like the static class implementation

2 comments:

  1. Another disadvantage would be a bunch of additional code (e.g. in the views etc.) to provide the logic. It kind of reduces the cleanliness of the code.

    Also, are there any performance catches with feature toggling? Especially, if there is a lot of features to be toggled.

    ReplyDelete
  2. Yeah, I agree it's not great cluttering your views with feature toggles, but, there's no way around it that I'm aware of. Regardless of how you implement your feature toggles, if you want to hide a link, for example, you have to add code to a view.

    I haven't noticed any performance hits with this implementation as you're nearly always reading them from the cache, but there were other problems. There were issues invalidating the cache so occasionally a toggle would be switched and nothing would happen. The latest implementation is significantly different from the one described in this blog but unfortunately I've not had time to write it up.

    ReplyDelete