Custom FeatureToggle Implementations for Non-Continuous-Delivery Usages

My open source fetaure toggling library contains a number of prebuilt toggles for common things such as enabling a feature based on the date, or a configuration value.

It’s also easy to create custom toggles by implementing IFeatureToggle.

Up to now, FeatureToggle has mainly been an aid for continuous delivery; a “half done” feature can simply be configured off so it doesn’t appear in the UI.

I’m wondering if the following approach has merit, namely treating conditionally available features as a first class citizens. So this is not just using them for continuous delivery but to encapsulate actual features of the application.

The example below requires 3 NuGet packages:

  • FeatureToggle.Core
  • FeatureToggle.WPFExtensions
  • MVVMLight

So the feature in the application will restrict the availability of mature rated games to customers who are 18+.

First off the feature toggle:

using FeatureToggle.Core;

namespace CustomFeatureToggle
{
    class MatureTitleSelectionFeature : IFeatureToggle
    {       
        public MatureTitleSelectionFeature(Customer customer)
        {
            FeatureEnabled = customer.Age >= 18;
        }

        public bool FeatureEnabled { get; set; }
    }
}

Here the business logic is encapsulated in the feature toggle and can be tested.

Next the viewmodel:

class MainViewModel : ViewModelBase
{
    private Customer _selectedCustomer;
    private IFeatureToggle _matureTitlesFeature;
    private ObservableCollection<Customer> _customers;

    public MainViewModel()
    {
        Customers = new ObservableCollection<Customer>
                    {
                        new Customer {Name = "Sarah", Age = 32},
                        new Customer {Name = "Robert", Age = 17}
                    };

        SelectedCustomer = Customers[0];

        MatureTitlesFeature = new MatureTitleSelectionFeature(SelectedCustomer);
    }

    public ObservableCollection<Customer> Customers
    {
        get
        {
            return _customers;                 
        }
        set
        {
            _customers = value; 
            Set(() => Customers, ref _customers, value);                 
        }
    }

    public Customer SelectedCustomer
    {
        get
        {
            return _selectedCustomer;
        }
        set
        {
            _selectedCustomer = value;
            
            Set(() => SelectedCustomer, ref _selectedCustomer, value);

            MatureTitlesFeature = new MatureTitleSelectionFeature(SelectedCustomer);
        }
    }

    public IFeatureToggle MatureTitlesFeature
    {
        get
        {
            return _matureTitlesFeature;
        }
        set
        {
            _matureTitlesFeature = value;

            Set(() => MatureTitlesFeature, ref _matureTitlesFeature, value);
        }
    }
}

Here, every time the selected customer changes, a new (immutable) toggle is created based on the customer’s details, i.e. Age.

The visibility in the UI of mature titles is simple data binding, using a visibility convertor from FeatureToggle.WPFExtensions.

<Window x:Class="CustomFeatureToggle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:toggles="clr-namespace:FeatureToggle.Toggles;assembly=FeatureToggle.WpfExtensions"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <toggles:FeatureToggleToVisibilityConverter x:Key="ToggleVisConverter"></toggles:FeatureToggleToVisibilityConverter>
    </Window.Resources>
    <Grid>
        <StackPanel>
            <ComboBox DisplayMemberPath="Name" 
                      ItemsSource="{Binding Customers, Mode=TwoWay}"
                      SelectedItem="{Binding SelectedCustomer}"></ComboBox>
            <TextBlock>All audience titles here</TextBlock>
            <TextBlock Visibility="{Binding MatureTitlesFeature, Converter={StaticResource ToggleVisConverter}, Mode=TwoWay}">Mature titles here</TextBlock>
        </StackPanel>
    </Grid>
</Window>

I’m wondering how this approach would scale out for larger apps.

screenshot showing mature visible

 

screenshot showing mature invisible

Add comment

Loading