Using BuildIt.States for Managing States

Almost every software development course at some point covers object orientated programming where the concept of encapsulation is drummed in. We’re taught to create classes that track state – a typical example is an Order that has a series of items, and then goes through various states as the order is processed. All this information is held within the Order object, including some basic functions such as calculating the total of the items being ordered. As the systems we work on grows in complexity, so does the complexity of the classes that are used to encapsulate aspects of the system. Unfortunately this often results in large, bloated classes, where it’s hard to make changes without fear of breaking other parts of the system.

One common mistake that seems to creep in over time is that it becomes difficult to manage what state a class is in. This can result from either a lack of documentation about what states the class can be in, or the states themselves aren’t clearly defined. Take the Order example, the Order class may have properties such as OrderTimestamp and OrderId which are set when the Order is placed. If the Order is rejected, the OrderTimestamp may be reset, leaving the class is some weird state where it has an OrderId, yet no OrderTimestamp. This is one of the scenarios that BuildIt.States is designed to help with.

Before we jump in, we need to set down a basic understanding of how we define states. States can appear in groups but within a group, there can only ever be one current state. For example in the Order scenario, there might be a group called TransactionStates, and the Order can only be in one of the states, Unprocessed, Processing, Processed, OrderRejected, at any given time. This leads me to the starting point of working with BuildIt.States: I’m going to define an enumeration that defines the states that my class can go between – you’ll notice this includes a Default (I often use Base instead) which BuildIt.States will use to determine if the state has been set or not.

public enum MainStates
{
    Default,
    One,
    Two,
    Three,
    Four
}

The next thing we need is our class, in this case one that inherits from NotifyBase, and raises a PropertyChanged event when the CurrentState property changes.

public class MainViewModel:NotifyBase
{
    private string currentState;

    public string CurrentState
    {
        get { return currentState; }
        set
        {
            currentState = value;
            OnPropertyChanged();
        }
    }
}

Defining the states that this class can be in is as simple as adding a reference to the BuildIt.States NuGet package and then defining each of the states:

public IStateManager StateManager { get; } = new StateManager();

public MainViewModel()
{
    StateManager
        .Group<MainStates>()

        .DefineState(MainStates.One)
        .ChangePropertyValue(vm => CurrentState, “State One”)

        .DefineState(MainStates.Two)
        .ChangePropertyValue(vm => CurrentState, “State Two”)

        .DefineState(MainStates.Three)
        .ChangePropertyValue(vm => CurrentState, “State Three”)

        .DefineState(MainStates.Four)
        .ChangePropertyValue(vm => CurrentState, “State Four”);

}

The notation for defining state groups and states is very fluid in nature and we’re always looking for ways to make defining states more intuitive. Essentially each of these states updates a single property, CurrentState, with a new constant value.

Making use of this class is as simple as creating an instance of the MainViewModel and setting it as the DataContext for the page:

public sealed partial class MainPage : Page
{
    private MainViewModel ViewModel { get; } = new MainViewModel();
    public MainPage()
    {
        this.InitializeComponent();

        DataContext = ViewModel;
    }

    private void StateOneClick(object sender, RoutedEventArgs e)
    {
        ViewModel.StateManager.GoToState(MainViewModel.MainStates.One);
    }

    private void StateTwoClick(object sender, RoutedEventArgs e)
    {
        ViewModel.StateManager.GoToState(MainViewModel.MainStates.Two);
    }

    private void StateThreeClick(object sender, RoutedEventArgs e)
    {
        ViewModel.StateManager.GoToState(MainViewModel.MainStates.Three);
    }

    private void StateFourClick(object sender, RoutedEventArgs e)
    {
        ViewModel.StateManager.GoToState(MainViewModel.MainStates.Four);
    }
}

When this is run, clicking through each of the buttons triggers a state change in the MainViewModel instances. This in turn causes the CurrentState property to change, which is shown on the page via data binding. The really awesome thing about the way states are defined, is that you can have any number of properties being set, and the library is smart enough to set the property values back to what they were originally when the class moves to a different state.

*Note that this library is currently in beta

Leave a comment