FeatureToggle v4 RC2 with .NET Core Configuration Changes

FeatureToggle logo

The pre-release RC2 version of FeatureToggle with .NET Core support is now available on NuGet.

See release notes and GitHub issues for additional background/breaking changes/limitations.

RC2 builds on RC1 and modifies the format of the json settings to make use of nesting as discussed in this issue, for example:

{
  "FeatureToggle": {
    "Printing": "true",
    "Saving": "false"
  }
}

Thanks to @steventmayer for the suggestions.

FeatureToggle v4 RC1 with .NET Core Support

The pre-release RC1 version of FeatureToggle with .NET Core support is now available on NuGet.

See release notes and GitHub issues for additional background/breaking changes/limitations.

The main drive for v4 is to add initial .NET Core support.

Using Feature Toggle in a .NET Core Console App

In Visual Studio 2017, create a new .NET Core Console App and install the NuGet package. This will also install the dependent FeatureToggle.NetStandard package (.NET Standard 1.4).

Add the following code to Program.cs:

using System;
using FeatureToggle;

namespace ConsoleApp1
{

    public class Printing : SimpleFeatureToggle { }
    public class Saving : EnabledOnOrAfterDateFeatureToggle { }
    public class Tweeting : EnabledOnOrAfterAssemblyVersionWhereToggleIsDefinedToggle { }

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Printing();
            var s = new Saving();
            var t = new Tweeting();

            Console.WriteLine($"Printing is {(p.FeatureEnabled ? "on" : "off")}");
            Console.WriteLine($"Saving is {(s.FeatureEnabled ? "on" : "off")}");
            Console.WriteLine($"Tweeting is {(t.FeatureEnabled ? "on" : "off")}");


            Console.ReadLine();
        }
    }
}

Running the application will result in an exception due to missing appSettings.config file: “System.IO.FileNotFoundException: 'The configuration file 'appSettings.json' was not found and is not optional.“ By default, FeatureToggle will expect toggles to be configured in this file, add an appSettings.json and set its Copy To Output Directory to “Copy if newer” and add the following content:

{
  "FeatureToggle.Printing": "true",
  "FeatureToggle.Saving": "01-Jan-2014 18:00:00",
  "FeatureToggle.Tweeting": "2.5.0.1" // Assembly version is set to 2.5.0.0
}

Running the app now result in:

Printing is on
Saving is on
Tweeting is off

Using Feature Toggle in an ASP.NET Core App

Usage in an ASP.NET core app currently requires the configuration to be provided when instantiating a toggle, this may be cleaned up in future versions. For RC1 the following code shows the Startup class creating a FeatureToggle AppSettingsProviderand and passing it the IConfigurationRoot from the startup class.

public void ConfigureServices(IServiceCollection services)
{
    // Set provider config so file is read from content root path
    var provider = new AppSettingsProvider { Configuration = Configuration };

    services.AddSingleton(new Printing { ToggleValueProvider = provider });
    services.AddSingleton(new Saving { ToggleValueProvider = provider });

    // Add framework services.
    services.AddMvc();
}

The appSettings would look something like the following:

{
  "FeatureToggle.Printing": "true",
  "FeatureToggle.Saving": "false",
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

As an example of using this configuration check out the example project on GitHub, in particular the following:

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Models/Printing.cs

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Models/Saving.cs

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/ViewModels/HomeIndexViewModel.cs

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Controllers/HomeController.cs

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Views/Home/Index.cshtml

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/Startup.cs

https://github.com/jason-roberts/FeatureToggle/blob/master/src/Examples/AspDotNetCoreExample/appsettings.json

New FeatureToggle Release: v3.4 With Fluent Syntax

FeatureToggle is an open source feature toggling / feature switching library for .NET.

Version 3.4 Introduces an new additional way to get the value of whether a toggle is enabled or not.

In versions to v3.3 and earlier, to get the value of a toggle, an instance of the toggle class needed to be created manually:

new SampleFeatureToggle().FeatureEnabled

With v3.4 a new additional fluent way is introduced to improve readability and offer a convenience when evaluating a toggle.

First reference the FeatureToggle.Core.Fluent namespace, then the Is<T> class can be used as follows:

Is<SampleFeatureToggle>.Enabled
Is<SampleFeatureToggle>.Disabled

To make the fluent style a little more readable, the name of the concrete toggle class can be shorted, so rather than PrintFeatureToggle for example, it could be named Print, the code would then read:

Is<Printing>.Enabled
Is<Printing>.Disabled

FeatureToggle v3.3 Released

FeatureToggle is an open source feature toggling library for .NET.

Version 3.3 was just released to NuGet and includes two minor new features as described below.

FallbackValueDecorator

The FallbackValueDecorator allows you to wrap (decorate) a primary toggle and specific a fallback toggle to be used if the primary toggle fails or is not configured.

new FallbackValueDecorator(new MyPrimaryToggle(), new MyFallbackToggle());

An optional overload allows the specifying of an Action<Exception> to be called if the primary toggle errors for example to perform some logging or alerting:

public FallbackValueDecorator(IFeatureToggle primaryToggle, IFeatureToggle fallbackToggle, Action<Exception> logAction = null)

CompositeOrDecorator

The CompositeOrDecorator allows the specification of two toggle instances, if either one of the toggles is enabled the decorator will return true:

new CompositeOrDecorator(new AnEnabledFeature(), new ADisabledFeature());


If you’re new to the concept of feature toggling or FeatureToggle check out my Pluralsight course Implementing Feature Toggles in .NET with FeatureToggle or the documentation.


Thanks to Craig Vermeer for the work investigating failing convention tests in VS2015 for this release.

FeatureToggle 3.2 Released

FeatureToggle logo image

A minor release of my open source FeatureToggle library has just been released to NuGet.

Version 3.2 was a result of user requests to be able to configure toggles that get their values from sql server to be configured using the <connectionStrings> section of the .config file.

A Sql based toggle can now be configured a number of different ways

Using appSettings only

This is the original method:

<appSettings>
   <add key="FeatureToggle.SaveToPdfFeatureToggle.ConnectionString" value="Data Source=.\SQLEXPRESS;Initial Catalog=FeatureToggleDatabase;Integrated Security=True;Pooling=False"/>
   <add key="FeatureToggle.SaveToPdfFeatureToggle.SqlStatement" value="select Value from Toggle where ToggleName = 'SaveToPdfFeatureToggle'"/>
</appSettings>

Using connectionStrings Entry by Convention

<appSettings>
    <add key="FeatureToggle.SaveToPdfFeatureToggle.SqlStatement" value="select Value from Toggle where ToggleName = 'SaveToPdfFeatureToggle'"/>
</appSettings>

<connectionStrings>
    <add name="FeatureToggle.SaveToPdfFeatureToggle" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=FeatureToggleIntegrationTests;Integrated Security=True;Pooling=False" />    
</connectionStrings>

 

Using connectionStrings Custom Named Entry

This option allows multiple toggles to share a named connection if you have more than one sql toggle in the application.

<appSettings>
    <add key="FeatureToggle.SaveToPdfFeatureToggle.SqlStatement" value="select Value from Toggle where ToggleName = 'SaveToPdfFeatureToggle'"/>
    <add key="FeatureToggle.SaveToPdfFeatureToggle.ConnectionStringName" value="myAwesomeConnection" />
</appSettings>

<connectionStrings>
    <add name="myAwesomeConnection" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=FeatureToggleIntegrationTests;Integrated Security=True;Pooling=False" />    
</connectionStrings>

Thanks

Thanks to the following people for contributions and ideas:

Improving Test Code Readability and Assert Failure Messages with Shouldly

Shouldly is an open source library that aims to improve the assert phase of tests; it does this in two ways. The first is offering a more “fluent like” syntax that for the most part leverages extension methods and obviates the need to keep remembering which parameter is the expected or actual as with regular Assert.Xxxx(1,2) methods. The second benefit manifests itself when tests fail; Shouldly outputs more readable, easily digestible test failure messages.

Failure Message Examples

The following are three failure messages from tests that don’t use Shouldly and instead use the assert methods bundled with the testing framework (NUnit, xUnit.net, etc):

  • “Expected: 9  But was:  5”
  • “Assert.NotNull() Failure”
  • “Not found: Monday In value:  List<String> ["Tuesday", "Wednesday", "Thursday"]”

In each of the preceding failure messages, there is not much helpful context in the failure message.

Compare the above to the following equivalent Shouldly failure messages:

  • “schedule.TotalHours should be 9 but was 5”
  • “schedule.Title should not be null or empty”
  • “schedule.Days should contain "Monday" but does not”

Notice the additional context in these failure messages. In each case here, Shouldly is telling us the name of the variable in the test code (“schedule”) and the name of the property/field being asserted (e.g. “Total Hours”).

Test Code Readability

For the preceding failure messages, the following test assert code is used (notice the use of the Shouldly extension methods):

  • schedule.TotalHours.ShouldBe(9);
  • schedule.Title.ShouldNotBeNullOrEmpty();
  • schedule.Days.ShouldContain("Monday");

In these examples there is no mistaking an actual value parameter for an expected value parameter and the test code reads more “fluently” as well.

To find out more about Shouldly check out the project on GitHub, install via NuGet, or checkout my Better Unit Test Assertions with Shouldly Pluralsight course.

FeatureToggle Version 3 Released

FeatureToggle logo image

Version 3 of my open source feature toggle library is now released to NuGet.

Version 3 introduces some breaking changes and new features.

Breaking Changes

  • The WPF value convertor package has been removed for version 3 as it’s trivial to implement a version in individual applications and reduce the maintenance overhead for the porject
  • Version 3 removes support for Windows Phone 8.0 (you can still use version 2.x if you need this support)

New Features

Platforms Support

In addition to .NET framework 4 full, version 3 also supports:

  • Windows Phone 8.1 Silverlight apps
  • Windows Universal Apps 8.1 (Store and Windows Phone 8.1 WinRT)
  • Windows Store 8.1 apps

Future versions will add support for Windows 10 apps.

New Toggle Types

The EnabledOnOrAfterAssemblyVersionWhereToggleIsDefinedToggle (a little verbose I know) allows a feature to become enabled once a specified assembly version number is reached. The assembly version used is that of the assembly inside which the toggle is defined, rather that the executing assembly. The configuration value for this toggle would be (for example) 0.0.2.1.

Future version will add support for comparing the executing assembly version.

New Decorators

A new type of feature that version 3 introduces is the idea of toggle decorators. These are classes that “wrap” one or more toggles and provide additional features.

The DefaultToEnabledOnErrorDecorator and the DefaultToDisabledOnErrorDecorator allows a default value to provided if there is an error evaluating the wrapped toggle value, for example with a configuration error. These decorators should be used with caution as your application may end up in an unknown state if you forget to configure something properly. In some cases you may want this behaviour rather than the application failing.

Assuming that a feature toggle called MyFeatureToggle has been defined, to use the decorator the following code would be used.

IFeatureToggle printFeatureThatDefaultsToDisabled = new DefaultToDisabledOnErrorDecorator( new MyFeatureToggle() );

bool isPrintEnabled = printFeatureThatDefaultsToDisabled.FeatureEnabled;

These decorators also allow you to specify an optional logging action that gets called if the wrapped toggle throws an exception:

new DefaultToDisabledOnErrorDecorator(wrappedToggle, ex => Console.WriteLine(ex.Message));

 

The CompositeAndDecorator allows multiple toggles to be wrapped, only if all these wrapped toggles are enabled will the decorator return true.

IFeatureToggle andToggle = new CompositeAndDecorator(new AnEnabledFeature(), new ADisabledFeature());

var isEnabled = andToggle.FeatureEnabled; // returns false

 

The final new decorator is the FixedTimeCacheDecorator. This allows a toggle that gets its value from a slow source (such as remote database, http, etc.) to have its value cached for a fixed period of time. To use this you specify the wrapped toggle and a TimeSpan.

IFeatureToggle cachedToggle = new FixedTimeCacheDecorator(cachedToggle, TimeSpan.FromSeconds(10));

 

Check out the release notes on GitHub. If you find any problems or bugs or want to suggest other features, please create an issue on GitHub.

An Update on FeatureToggle v3 Development

The next version of my open source feature toggling library is currently in development.

Version 3 will introduce a number of new features and retire support for some older platforms. For the currently implemented changes (not yet released at the time of writing) see GitHub release notes, and the complete list of v3 issues/features.

Some notable additions include some new toggle types to enable scenarios such as automatically enabling a feature once the assembly version number meets or exceeds a specific version and decorators to allow a toggle to default to on or off if the underlying toggle errors in some way, such as missing configuration or network error while retrieving the toggle value from a remote source such as SQL Server.

Once v3 development is complete it will be available via NuGet.

Open Source Thanks

In a previous post (5 Ways to Contribute to Open Source - It’s Not All Code) I mentioned the simplest way to be involved in open source is to simply Tweet about the project or by saying thanks to the creator/contributors. In the post i said “Most open source authors don’t get paid, saying thankyou is not only nice but is good encouragement for the authors to keep the project going”.

I’d like to propose the hashtag #opensourcethanks – it would be great to see the Twitter search for this hashtag fill up with thankyous :)

If you’re benefitting from an open source project, take a minute to send a thankyou Tweet.

Tracking Technical Debt with TechDebtAttributes

Technical debt can build up over time, slows down development speed, and could increase the risk of defects.

If you work in situation where it’s not always possible to create clean code or you’ve inherited a legacy application you may wish to start cataloguing where and how painful tech debt is.

Introducing TechDebtAttributes

image

I just released an initial NuGet version of an open source project called TechDebtAttributes.

It allows attributes to be used to mark classes, methods, etc as containing technical debt.

When the [TechDebt] attribute is applied you need to specify 2 mandatory values: pain and effort to fix.

Pain is a relative measure of how painful the tech debt is; for example how much it slows you down when changing code, how unhappy you are with it, how many defects are caused by it, etc.

Effort to fix is also a relative measure of the ease, amount of effort/time it will take to fix and remove the debt.

Optionally a description of the debt can also be specified.

Once attributes have been applied, a (string) report can be generated:

***Start of Tech Debt Report - finding all [TechDebt] attribute usages

Benefit to fix: 4999.5  AnotherExampleUsageAssembly.Mango Pain:9999 Effort to fix:2
Benefit to fix: 1666.7  Void .ctor() Pain:5000 Effort to fix:3
Benefit to fix: 5 Quick fix to stop stupid stuff happening sometimes Void SomeMethod() Pain:5 Effort to fix:1
Benefit to fix: 2  ExampleUsage.SillyEnum Tomato Pain:47 Effort to fix:23
Benefit to fix: 0.5 What kind of cheese is this? ExampleUsage.Cheese Pain:3 Effort to fix:6
Benefit to fix: 0.4 What exactly is inner cheese ExampleUsage.Cheese+InnerCheese Pain:3 Effort to fix:8
Benefit to fix: 0.3 This really is silly ExampleUsage.SillyEnum Pain:2 Effort to fix:6
Benefit to fix: 0.2 This is dumb, we should remove it ExampleUsage.ISomeDumbInterface Pain:10 Effort to fix:44
Benefit to fix: 0.1 This should be moved to it's own interface Void Y() Pain:10 Effort to fix:100
Benefit to fix: 0 There's a lot of work to fix this whole class for not much gain ExampleUsage.SomeThing Pain:1 Effort to fix:200

***End of Tech Debt Report.

You can also use a method to specify the maximum total pain you’re willing to accept, if the total pain from all [TechDebt] attributes exceeds this an exception will be thrown and your test will fail.

See the Readme on GitHub for more info.