DEV Community

loading...

AVOIDING IF_ELSE HELL

VenkteshV
惻Updated on 惻2 min read

All developers at some point are faced with a dilemma. They are asked to Fit in a variety of scenarios and hence end up writing if-else conditionals and reach a point where code becomes messy. Weeks later the dev may not even understand the code he wrote. Well if at some point you have felt the if else ladder you wrote is obnoxious or haunting welcome to the club.In this post I would like to humbly represent one instance where I was able to avoid the if-else hell by applying an existing pattern and a library.

There was a requirement in our application to update a status history table where we maintain the various status of document processing like upload, download etc.We maintain various states like extracted, uploading,downloading,uploaded etc. and hence we needed a validation logic to make sure the states are not updated in wrong order so we had to establish a small validation system to ensure other developers don't break the order as it would lead to serious cascading failures in the big picture. So I decided not to write conditional and wrap it up this time.When I stared at the acceptance criteria and the states I realized a pattern. After all these are states a document goes through and voila I got a solution,State Machine. And since the app was in .net core I decided to use the "Stateless" package to achieve the same. So let's jump to the example.

    public ProcessState Status
    {
        get
        {
            return _stateMachine.State;
        }
    }


         public StatelessStateMachine(ProcessState state)
    {
        _stateMachine = new StateMachine<ProcessState, ProcessStateTransitionTriggers>(state);
        _stateMachine.Configure(ProcessState.Extracted)
            .Permit(ProcessStateTransitionTriggers.moveToQueuedForDownload, ProcessState.QueuedForDownload);

        _stateMachine.Configure(ProcessState.QueuedForDownload)
            .Permit(ProcessStateTransitionTriggers.moveToDownloading, ProcessState.Downloading);

        _stateMachine.Configure(ProcessState.Downloading)
           .Permit(ProcessStateTransitionTriggers.moveToDownloaded, ProcessState.Downloaded);

        _stateMachine.Configure(ProcessState.Downloaded)
         .Permit(ProcessStateTransitionTriggers.moveToQueuedForUpload, ProcessState.QueuedForUpload);

    }

Explanation :
_statemachine.State returns the current status.
Next the first line in the function below is used to instantiate the List of states and the triggers(ProcessState and ProcessStateTransitionTriggers are enums containing the list of states and triggers respectively).So when a trigger is fired depending on the state specified in the permit true or false will be returned to indicate if the state transition is valid or not.

{
_stateMachine.Configure(ProcessState.Extracted)
.Permit(ProcessStateTransitionTriggers.moveToQueuedForDownload, ProcessState.QueuedForDownload);
}

For example in the above code translates to if the current state is Extracted then permit the transition to state "QueuedForDownload" if the transition trigger is moveToQueuedForDownload

{_stateMachine.CanFire(trigger)}

The above line will fire the validation and if it returns true the update can be performed using

{_stateMachine.Fire(trigger)}

In the above example "trigger" will be "moveToQueuedForDownload".

Conclusion:

Hence a lot of common obnoxious code we force ourselves to write can be avoided by relating to existing patterns.

Discussion (0)