What is Feature Toggling and how to implement in .Net
What is Feature Toggling?
Feature toggle is a modern software development practice which allows the team to modify the system behavior without changing the code. Feature toggling is a set of patterns which can help a team to deliver new functionality to users rapidly but safely.
Feature toggling is a way to turn on / off feature within the application.
Why use Feature Toggling?
Feature toggling allow to release unused code to production without creating the need to create the feature branches and later go through the painful merging exercise.
Feature toggling helps release go smoothly without worrying about the environment contention e.g. DEV / Staging.
Feature toggling also promotes the Continuous Integration/Continuous Delivery.
Feature toggling also promotes the rapid application development. Various popular frameworks such as SAFe, Spotify encourage to use feature toggling.
Broad Categories of Feature Toggles
Following are the broad categories of feature toggles:
? Release Feature Toggles ? Business Feature Toggles ? Operational Feature Toggles ? Experimental Feature Toggles
Release Feature Toggles
Release toggle is an internal technical tool that the helps development team manage their development processes. Release toggle enables the trunk-based development. It also removes the need to create separate branches for each release and later painful merging of branches.
It allows in-progress features to be checked into a shared integration branch (e.g. master or trunk) while still allowing that branch to be deployed to production at any time.
Release toggles allow incomplete and un-tested code paths to be shipped to production as latent code which may never be turned on. Release feature toggles are short lived.
Business Feature Toggles
Business feature toggle is about tailoring the experience of the application for business related purposes. This is about exposing particular application functionality based upon the certain rules or behavior. For example, premium users in the application would see the paid functionality while the free user would not see that functionality.
Business feature toggles live longer even for the entire lifetime of the application.
Operational Feature Toggles
Operational feature toggles are used to control the operational aspect of an application.
Use this toggle when rolling out the new feature which has unclear performance implication so that system operators can disable the feature in production when needed.
These toggles are also used to degrade the non-vital system functionality in case of heavy load. For example during the heavy load system operators can disable the “Product Reviews” and “Recommended Products” functionality on the product details page as these are non-vital functionalities and are expensive to generate. This is the type of switch is also called “kill switch”.
These toggles are both short lived and long lived depending upon the use case. For example, short lived for the new release feature but long-lived for the kill switches.
Experimental Feature Toggles
These type of feature toggles helps A/B testing and Canary testing.
A/B testing: Each user of the system is placed into a group and at runtime, route the user to the one code path or the other. By tracking the aggregate behavior of different groups we can compare the effect of different code paths. This technique is commonly used to make data-driven optimizations to things such as the purchase flow of an eCommerce system, or the Call To Action wording on a button.
Canary testing: Turn On the new feature for the few users or the group of users only and constantly monitor the performance of new feature. Once gain the confidence on new features, turn On for the rest of the users.
These type of toggles are short live.
Toggle Configuration
There are three configuration options for feature toggles: ? Compiled Configuration ? Local Configuration ? Centralized Configuration
Compiled Configuration
This type of configuration is hard-coded in the code. Features can only be enabled/disabled with new release via code deployment.
If deployment on multiple machines e.g. VMs, then multiple machines need to be in sync.
This type of configuration is also called static configuration since it requires code deployment for toggle On/Off.
Local Configuration
Add the toggle configuration in the application configuration file e.g. app.confg or web.config file. Configuration can be turned On/Off without the need of new release.
If deployment on multiple machines e.g. VMs, then multiple machines need to be in sync
This configuration also called runtime/dynamic configuration.
Centralized configuration
This is the specialized type of configuration in which toggle configuration values are stored in the centralized location i.e. SQL Server database or the central file.
This type of configuration can be turned On/Off without the need of new release.
This configuration option is good for the Business and Operation feature toggling in which you can develop UI on top of central configuration to provide business/ops team the?ability to change the configuration without the need to change the central configuration manually.
This type of configuration is also good for the scenario where toggling is required in multiple applications e.g. web app and mobile app and turning feature On/Off reflects in all the applications.
Toggle Considerations
Toggle removal
With adding the toggles in the code, especially for the Release Feature Toggles, your code could easily become the “toggle hell”. To avoid this, you need to have the toggle removal strategy in place.
One option is to remove the feature toggle of the previous release in the next release.
On the other hand Business Features Toggles/Operational Feature Toggles are long-lived and may live for the life of an application.
Toggle decision points
You have different options to add the toggle decision points:
At the edge: This is where user request first enter for example publicly exposed web pages or APIs.
In the core: For more complex scenario or if new functionality being added or existing functionality being modified based upon certain rules.
User interface: Enable/disable button or functionality on the UI.
Design Considerations
Don’t use too many if/else. Use object-oriented pattern e.g. Strategy pattern.
Also, Keep decision point and decision logic separate.
Feature Toggling has a tendency to become more and prevalent in a code over the time and you will end up seeing more and more modules becoming coupled to the feature toggling system as a global dependency. This is not an ideal scenario.
To solve this coupling issue, you can adopt the Inversion of Control design pattern in your code.
Default values
Use the default values to avoid crashes. Also use the default value in the Off mode so even if you forget to add the configuration, a feature will not be turned On accidently.
Testing Feature Toggling
Feature toggling adds complexity into the system. You need to test all the code paths which require testing on both On/Off mode. If the dynamic configuration is applied then change the configuration to test in On/Off mode. If the static configuration is applied then deploy the code to test both On/Off modes.
When test the On mode, test as per the expected behavior of the On mode in the production point in time, as the feature may not be completed. What does this mean is that for example if you add the feature in Off mode which requires particular functionality to change but feature is partially implemented, you would need to test that partial implementation as this is the behavior you will be expecting in the code on production as well as list down the corrective actions you would need to take in case features gets accidentally turned On in production.
You should also implement the automated testing which will help you to test in both On/Off modes.
How to implement Feature Toggles
You can write your own custom code to implement the feature toggling but this approach promotes the use of “Magic String”. Writing the customer code promotes the runtime error or unexpected behavior due to non-existing feature or typo in the magic string. Also with the custom code approach, removal of the feature is difficult as it doesn’t support the compile time errors.
Another option is to use the open source library. Open source library provides the strong type and catches the compile time errors. Open source library is easy to implement and supports a wide variety of configuration options. Removal of the feature is easy with this approach as it catches the compile time errors.
Some of the Open source libraries for feature toggling are: ? NFeature ? FeatureSwitcher ? nToggle ? FeatureToggle
We will use the FeatureToggle library to implement feature toggle in .Net.
FeatureToggle library
FeatureToggle library is the open source .Net library to implement the feature toggling in your .Net code.
FeatureToggle library supports following types of feature toggles: ? AlwaysOffFeatureToggle ? AlwaysOnFeatureToggle ? SimpleFeatureToggle ? EnabledOnOrAfterDateFeatureToggle ? EnabledOnOrBeforeDateFeatureToggle ? EnabledBetweenDatesFeatureToggle ? RandomFeatureToggle ? EnabledOnDaysOfWeekFeatureToggle ? SqlFeatureToggle ? BooleanRavenDBFeatureToggle
To use this library create the new ASP.Net MVC application and add the FeatureToggle nugget packages in your code:
Once you add the nugget package it will add the relevant dependent packages.
I will explain how you can use a different toggling option of FeatureToggle library.
In this example, we will create a simple ASP.Net MVC application which will have button “Premium Products” enabled/disabled based on the feature toggle.
AlwaysOffFeatureToggle / AlwaysOnFeatureToggle
This type of toggling option is hard-coded in the code. You enabled/disabled feature using the AlwaysOffFeatureToggle or AlwaysOnFeatureToggle toggle.
These toggles work as Boolean true/false and compiled into the assembly.
This type of configuration is the static type of configuration and used in the Release toggles.
If you disable the feature in one release than enable it in the next release with the code deployment since the configuration is hardcoded in the assembly.
Now to use the AlwaysOffFeatureToggle first create the class called PremiumProductsFeature and inherit from the AlwaysOffFeatureToggle class.
public class PremiumProductsFeature : AlwaysOffFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
?
To enable the feature in the next release we will inherit the class PremiumProductsFeature from AlwaysOnFeatureToggle.
AlwaysOffFeatureToggle.FeatureEnabled returns the Boolean false while the AlwaysOnFeatureToggle.FeatureEnabled returns the Boolean true.
SimpleFeatureToggle
Use this feature to enable/disable feature based on configuration. You can add the configuration in the application configuration file e.g. web.config or app.config file. This option supports the supports runtime/dynamic configuration.
Following the above example, we will use the SimpleFeatureToggle enable/disable the “Premium Products” based on the configuration defined in the web.config file.
Create the class called PremiumProductsFeature and inherit from the SimpleFeatureToggle class.
public class PremiumProductsFeature : SimpleFeatureToggle
{
}
Next, create the setting with the key FeatureToggle.PremiumProductsFeature and value true/false in the appSettings section of web.config
<add key="FeatureToggle.PremiumProductsFeature" value="false" />
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle.
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
To enable the feature we don’t need to wait for the next release. We can simply change the value of setting FeatureToggle.PremiumProductsFeature to true and feature will be enabled.
EnabledOnOrAfterDateFeatureToggle / EnabledOnOrBeforeDateFeatureToggle / EnabledBetweenDatesFeatureToggle
This type of feature toggle automatically enable/disable feature based on the date. It supports the type of toggling as the name suggests. You can add the configuration in the application configuration file e.g. web.config or app.config file. This option supports the supports runtime/dynamic configuration.
EnabledOnOrAfterDateFeatureToggle: enables the feature automatically on or after certain data and before that date feature is disabled.
EnabledOnOrBeforeDateFeatureToggle: enables the feature at the time of implementation and disables the feature automatically on or after the certain date.
领英推荐
EnabledBetweenDatesFeatureToggle: automatically enables the feature during certain dates range and automatically disable the feature outside of that date range.
Following the above example, we will use EnabledOnOrAfterDateFeatureToggle to enable “Premium Products” after a certain date. We will define the date configuration value in the web.config file.
Create the class called PremiumProductsFeature and inherit from the EnabledOnOrAfterDateFeatureToggle class.
public class PremiumProductsFeature : EnabledOnOrAfterDateFeatureToggle
{
}
Next, create the setting with the key FeatureToggle.PremiumProductsFeature and in the value enter the date when we want the feature to be enabled in the appSettings section of web.config file.
Assuming today is 17-Sep-2017 and we want Premium Product button to be enabled on or after 17-Dec-2017 at 1:00 pm. We need to add the value as “17-Dec-2017 13:00:00”. Note the format should be 2 digits date, three letter month name and 4 digit year. Time should be in the 24 hours format.
<add key="FeatureToggle.PremiumProductsFeature" value="17-Dec-2017 13:00:00" />
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle.
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
With this setup, “Premium Products” button will auto enable on 17-Dec-2017 at 1:00 pm.
To use the EnabledOnOrBeforeDateFeatureToggle or EnabledBetweenDatesFeatureToggle inherit the class PremiumProductsFeature from EnabledOnOrBeforeDateFeatureToggle or EnabledBetweenDatesFeatureToggle class.
To specify the date range for EnabledBetweenDatesFeatureToggle, enter the from and to date in the value delimited with the pipe “|”.
For example, to enable the feature between 1-Jan-2018 1:00 pm to 1-Jun-2018 1:00 pm, you enter the value as “1-Jan-2018 13:00:00 | 1-Jun-2018 13:00:00”.
EnabledOnDaysOfWeekFeatureToggle
This type of toggle automatically enables the feature on certain days of week defined in the configurations. It supports the runtime/dynamic configuration.
Following the above example, we will use EnabledOnDaysOfWeekFeatureToggle to enable “Premium Products” on certain weekdays. We will define the date configuration value in the web.config file.
Create the class called PremiumProductsFeature and inherit from the EnabledOnDaysOfWeekFeatureToggle class.
public class PremiumProductsFeature : EnabledOnDaysOfWeekFeatureToggle
{
}
Next, create the setting with the key FeatureToggle.PremiumProductsFeature and in the value enter days of the week when we want the feature to be enabled in the appSettings section of web.config file.
We want Premium Product button to be enabled on Monday, Tuesday, and Wednesday.
<add key="FeatureToggle.PremiumProductsFeature" value="Monday, Tuesday, Wednesday" />
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
With this setup, “Premium Products” button will auto enable on Monday, Tuesday, and Wednesday and will be disabled on the other weekdays.
RandomFeatureToggle
This toggle randomly enables/disables the feature. It provides no support of configuration. This toggle is used for used for A/B testing to randomly test the feature On/Off.
Following the above example, we will use RandomFeatureToggle to randomly enable/disable “Premium Products”.
Create the class called PremiumProductsFeature and inherit from the RandomFeatureToggle class.
public class PremiumProductsFeature : RandomFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle.
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
With this setup, “Premium Products” button will be randomly enabled/disabled.
SqlFeatureToggle
Use this toggle to enable/disable feature based on the configuration defined in SQL Server. This type of toggle supports the central configuration option.
With this toggle, you either create the separate toggling database or keep the toggling configuration in the application database.
Following the above example, we will use the SqlFeatureToggle to enable/disable the “Premium Products” based on the value in the database.
To start with, create a new database called “MyToggleConfiguration”. Create a new table called “ToggleConfigurations” in the new database. Add columns called ToggleName and ToggleValue in the ToggleConfigurations table.
Next, add the connection string in the connectionStrings section web.config file:
<add key="FeatureToggle.PremiumProductsFeature.ConnectionString" value="Data Source=.\SQLEXPRESS;Initial Catalog= MyToggleConfiguration;Integrated Security=True;Pooling=False"/>
?
Next, add the SQL query to retrieve the toggle value in the appSettings section the web.config file:
<add key="FeatureToggle.PremiumProductsFeature.SqlStatement" value="SELECT ToggleValue FROM ToggleConfigurations WHERE ToggleName = 'PremiumProductsFeature'"/>
?
Create the class called PremiumProductsFeature and inherit from the SqlFeatureToggle class.
public class PremiumProductsFeature : SqlFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
?
To enable/disable the Premium Product button, change the value of ToggleValue true/false in the ToggleConfigurations for the ToggleName matches PremiumProductsFeature.
BooleanRavenDBFeatureToggle
Use this toggle to enable/disable feature based on the configuration defined in Raven DB. This type of toggle supports the central configuration option.
With this toggle, you either create the separate toggling database or keep the toggling configuration in the application database.
Following the above example, we will use the BooleanRavenDBFeatureToggle to enable/disable the “Premium Products” based on the value in the database.
To start with, add the nugget package FeatureToggle.RavenDB.
Next, create a new database called “MyToggleConfiguration”. Create a new document called “PremiumProductsFeature” with the property called Enabled in the new database.
{
“Enabled”: false
}
Next, add the connection string in the connectionStrings section web.config file:
<add name="FeatureToggle.PremiumProductsFeature" connectionString="Url = https://localhost:8080;database= MyToggleConfiguration "/>
Create the class called PremiumProductsFeature and inherit from the BooleanRavenDBFeatureToggle class.
public class PremiumProductsFeature : BooleanRavenDBFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
To enable/disable the Premium Product button, change the value of Enabled property in the PremiumProductsFeature document in the Raven DB name ToggleConfigurations.
Custom Toggle
You create the custom toggle by inhering from the interface IFeatureToggle.
The custom toggle is good for the Experimental Feature Toggles where you want to perform the A/B testing or Canary testing based on the selected set of user.
Following our example above, we will enable the “Premium Products” button if a user is the premium user.
We will implement our custom toggle based on the user current context.
To start with, create a new class called PremiumProductsFeatureToggle and inherit from the IFeatureToggle. We will implement the property FeatureEnabled which will return the UserContext of IsPremiumUser.
class PremiumProductsFeatureToggle : IFeatureToggle
{
public bool FeatureEnabled
{
get
{
return UserContext.IsPremiumUser;
}
}
}
Next, we will create the UserContext which will have the IsPremiumUser property:
static class UserContext
{
public static bool IsPremiumUser
{
get
{
// Hardcoded. In the real world, you will get this value from the user principal or the database.
You can also use our logic to select 1% of the users for the A/B testing.
return false;
}
}
}
Next, we will create the class called PremiumProductsFeature and inherit from the PremiumProductsFeatureToggle class.
public class PremiumProductsFeature : PremiumProductsFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
return new PremiumProductsFeature();
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle.
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
Now the button “Premium Products” will enable/disable based on the user context.
Custom Providers
So far we have seen that FeatureToggle gets the configuration from the application configuration file or the database but you can override this behavior and can provide your own configuration provider.
To create your own custom provider create a custom class and inherit it from the IBooleanToggleValueProvider class.
Following the above example, we will use the SimpleFeatureToggle enable/disable the “Premium Products” based on the user context configuration provided through our own custom configuration provider.
To start with, create a class called PremiumUserContextProvider and inherit it from IBooleanToggleValueProvider.
class PremiumUserContextProvider : IBooleanToggleValueProvider
{
public bool EvaluateBooleanToggleValue(IFeatureToggle toggle)
{
return UserContext.IsPremiumUser;
}
}
Next, we will create the UserContext which will have the IsPremiumUser property:
static class UserContext
{
public static bool IsPremiumUser
{
get
{
// Hardcoded. In the real world, you will get this value from the user principal or the database.
You can also use our logic to select 1% of the users for the A/B testing.
return false;
}
}
}
Create the class called PremiumProductsFeature and inherit from the SimpleFeatureToggle class.
public class PremiumProductsFeature : SimpleFeatureToggle
{
}
Next, create the model and create the property PremiumProductsFeature inside that model. Additionally, in the get, specify the ToggleValueProvider.
public class ProductModel
{
public PremiumProductsFeature PremiumProductsFeature
{
get
{
var toggle = new PremiumProductsFeature ();
toggle.ToggleValueProvider = new PremiumUserContextProvider ();
return toggle;
}
}
}
Next, in your model, you will display the “Premium Products” button based on PremiumProductsFeature toggle.
@if (Model.PremiumProductsFeature.FeatureEnabled)
{
<button>Premium Products</button>
}
Now the button “Premium Products” will enable/disable based on the user context.
Removing Toggle
While using the FeatureToggle library, removing the feature toggle is easy. Since FetureToogle library is type sensitive and throws error if the configuration is not defined, you can start in any order of removal. Best practice is to remove the configuration first. After you remove the configuration, the compiler will throw the error if you try to run the code. After that, you can start removing the classes and the code where toggle is used.