Sometimes an application requires that some features are enabled (or rules applied), or not, based on some context. What is the best way to solve such a problem?
A C# app I was working on for a worldwide company was used in many countries. Of course, each country had specific features that were enabled and rules that were applied only for them. The previous programmers had used a very naive approach to solve this problem: they tested the user’s country ID:
The app ended up being full of those ugly checks. Plus, if you don’t know the countries and their IDs and don’t have the database table under hand, good luck trying to figure out what users of which country should see this button.
I was absolutely not convinced by the first idea that came to my mind, but I decided to give it a try. I created an enum listing the countries:
Then I added a method to the Country entity:
And the checks turned into:
Well… it was a little better. It was much easier to see what features and rules applied to which country. But it still sucked. Mainly because it was hard to change. Imagine having a rule for France that would require to show or enable multiple buttons, links, table columns or whatever on multiple views. And imagine that Canada wants that same feature in the next release. It was still a huge “oh God no” for me to go and update all those checks to include those pesky Canadians. Add to that the fact that the pages and user controls (yes, it was a web forms app) were bloated with those checks, sometimes many of them entangled together, and you’ve got a huge mess on your hands. Time to sit back and think.
I remembered reading a while ago about feature toggles on Martin Fowler’s bliki, and I realized that this solution, although brought up in a static context (the way Fowler describes them, feature toggles are enabled or disabled generally in configuration - in our example, each country would have its own live version of the app, configured for its own needs), could be applied in a dynamic context like mine.
So I rolled all my changes back, and started from scratch:
You get the idea for the next step, I guess:
How I initialized the Features property for each country is not relevant to this article: you could store the feature switches for each country in a database table, in a configuration file, or even hard-code them for all I care (although this solution kind of defeats the purpose of removing hard-coded country references - but not completely). What’s important is that the feature checks were now much clearer:
Now that is a much better solution. The single responsibility principle is respected: the view only needs to know if a given feature is enabled or not to decide if it must render the button. It doesn’t need to know for which country the feature is enabled anymore.
Additionally, even if this check was found in multiple places, there was no need to change all those occurrences anymore to enable the feature for Canada. I only needed to toggle the feature on for the countries that needed it.
Feature toggle is a powerful tool that can be leveraged not only statically, through configuration, to enable or disable features on a per-deployment basis, but it can also be used dynamically, using some context information in a single deployment setup.Written on October 7th, 2014 by Manuel Guilbault