Safe .NET Feature Flags with FeatureToggle
Tags: csharp, devops, dotnet, codequality
Published: 2019-09-21 04:48:22

Yesterday [I wrote on Feature Flags](https://dev.to/integerman/fun-with-feature-flags-31jf) in a largely language-neutral overview article.

Today I want to discuss my library of choice for Feature Flags in .NET applications: [FeatureToggle](https://github.com/jason-roberts/FeatureToggle) by Jason Roberts.

Feature Toggle is a very small and dedicated library dedicated to a variety of flexible feature toggle variations.

In Feature Toggle, you define a toggleable feature as a class either extending from a FeatureToggle class such as `SimpleFeatureToggle` or the `IFeatureToggle` interface.

A simple feature definition would look like this:

```cs
public class UseNewAnalyzer : SimpleFeatureToggle
{
    
}
```

This feature can then be checked like this:

```cs
private static IResumeAnalyzer GetResumeAnalyzer()
{
    var useNewAnalyzer = new UseNewAnalyzer();
    if (useNewAnalyzer.FeatureEnabled)
    {
        return new RewrittenAnalyzer();
    }
    else
    {
        return new ResumeAnalyzer();
    }
}
```

The code above will look for an entry in the application's configuration file (`appSettings.json`, `web.config`, or `app.config` depending on what type of application is running) and parse that value as a boolean to determine if `FeatureEnabled` returns true or false.

A sample .NET Core `appSettings.json` file with a feature flag is listed here:

```json
{
  "FeatureToggle": {
    "UseNewAnalyzer": "true"
  }
}
```

# The Design of FeatureToggle

Empty / marker classes and instantiating an object just to check a property on it and throw it away? How could this be a good thing?

Well, it turns out that the reason the code looks like this is that Jason Roberts intentionally designed FeatureToggle to make it hard to make common mistakes associated with feature flags.

Because FeatureToggles will throw exceptions if the configuration setting associated with the toggle doesn't exist, this helps you catch bad application configurations instead of accidentally leaving features offline because a config change never got ported to a new environment.

Additionally, since FeatureToggle uses class names to look up configuration settings, there are no strings lurking in code that might have typos causing the wrong configuration setting to be checked.

This reduces some risks common with other feature flag libraries and that added degree of safety helps code quality and fights environment-specific bugs.

# Cleaning up the Sample Code

If the code above is giving you issues, it can be simplified via using a static property like the following:

```cs
public class UseNewAnalyzer : SimpleFeatureToggle
{
    private static readonly UseNewAnalyzer Instance = new UseNewAnalyzer();

    public static bool IsFeatureEnabled => Instance.FeatureEnabled;
}
```

```cs
private static IResumeAnalyzer GetResumeAnalyzer()
{
    if (UseNewAnalyzer.IsFeatureEnabled)
    {
        return new RewrittenAnalyzer();
    }
    else
    {
        return new ResumeAnalyzer();
    }
}
```

By using the static getter `IsFeatureEnabled`, calling code no longer has to create an instance of the feature class and the code reads a lot more simply. Additionally, you no longer have an empty class due to the static property and instance field.

# Different Types of FeatureToggles

FeatureToggle is also designed to be flexible and offer both extensibility via subclassing or using the `IFeatureToggle` interface.

For example, I could write an implementation that is only active on the weekends by writing the following:

```cs
public class OnlyOnWeekends : IFeatureToggle
{
    public bool FeatureEnabled
    {
        get
        {
            switch (DateTime.Today.DayOfWeek)
            {
                case DayOfWeek.Saturday:
                case DayOfWeek.Sunday:
                    return true;

                default:
                    return false;
            }
        }
    }
}
```

I'm not sure why you'd want this type of a feature toggle, but if you can use the framework to create something simple like this, it can definitely be used to create more advanced things.

The good news is you don't need to create more advanced things. FeatureToggle ships with a number of built in implementations:

- **SimpleFeatureToggle** - The example we've worked with up until this point. It reads a value from a configuration file.
- **EnabledOnOrAfterDateFeatureToggle** - A feature that is only available once a date has been reached. This can be used as a 'go live' date.
- **EnabledOnOrBeforeDateFeatureToggle** - A feature that is only available before a date has been reached. This can be used as a retirement date.
- **EnabledBetweenDatesFeatureToggle** - A feature that is only available between two dates
- **EnabledOnDaysOfWeekFeatureToggle** - A feature that is only available on certain days of the week.
- **AlwaysOnFeatureToggle** - Designates a feature that will always be activated no matter what. This can be used to migrate away from configuration management without ripping out the class entirely.
- **AlwaysOffFeatureToggle** - Similar to `AlwasOnFeatureToggle`, but will *never* be active.
- **HttpJsonFeatureToggle** - This makes a HTTP GET request to a location configured in the feature's configuration file and expects a result like `{"enabled": true}`, then parses that `enabled` value to determine if the feature is enabled. Bear in mind that this will be a synchronous web call and prone to errors due to network, internet, and firewall issues.
- **SqlFeatureToggle** - Using this, you would define both a connection string in your configuration as well as a SQL query that returns a single boolean value. This value is then the return value for whether the feature is enabled or not. Again, this is a synchronous operation that is prone to more errors than many of the other implementations.
- **EnabledOnOrAfterAssemblyVersionWhereToggleIsDefinedToggle** - Checks the current assembly version against one defined in the configuration file and activates the feature if the configured version has arrived. This can be used for planning features to go live with major release numbers without knowing the date those releases will ship


FeatureToggle is obviously very well equipped to deal with most basic needs and simple and extensible enough to be able to adapt to any custom needs you encounter.

---

If you'd like to learn more about FeatureToggle, check out [the GitHub repository](https://github.com/jason-roberts/FeatureToggle) and give the library a try.

If you want more learning material, watch Jason Robert's awesome [Pluralsight course](https://www.pluralsight.com/courses/dotnet-featuretoggle-implementing). This is how I first found out about the library and it's very interesting to watch an instructor give a course on a library they created.

---

Cover Photo by Kari Shea on Unsplash