Refactoring a Switch Statement

Introduction

This article describes refactoring a switch statement in order to reduce Cyclomatic complexity.

Background

Many developers would have scratched their heads in order to keep their Cyclomatic complexity under 10. In some cases, it is really not possible at first site. In this article, I have provided a way to do that. Take the example of a Device State machine. You have a number of device states as below:

public
 enum
 DeviceStatesEnum
{
PowerUp,
Waiting,
StandBy,
Inactive,
Active,
Start,
Ready,
Equilibrating,
StartRunning,
Running,
ShoutingDown,
ShoutDown,
WarmingUp,
Error
}

Using the code

Just download the code and run it.

public
 enum
 DeviceStatesEnum
{
PowerUp,
Waiting,
StandBy,
Inactive,
Active,
Start,
Ready,
Equilibrating,
StartRunning,
Running,
ShoutingDown,
ShoutDown,
WarmingUp,
Error
}

You have come up with the following class in order to handle the various states:

public
 class
 DeviceController
{
private DeviceStatesEnum _currentDeviceState = DeviceStatesEnum.ShoutDown;

public void ChangeDeviceState(DeviceStatesEnum deviceState)
{
switch (deviceState)
{
case DeviceStatesEnum.Active:
SetDeviceStateToActive();
break ;
case DeviceStatesEnum.Equilibrating:
SetDeviceStateToEquilibrating();
break ;
case DeviceStatesEnum.Error:
SetDeviceStateToError();
break ;
case DeviceStatesEnum.Inactive:
SetDeviceStateToInactive();
break ;
case DeviceStatesEnum.PowerUp:
SetDeviceStateToPowerUp();
break ;
case DeviceStatesEnum.Ready:
SetDeviceStateToReady();
break ;
case DeviceStatesEnum.Running:
SetDeviceStateToRunning();
break ;
case DeviceStatesEnum.ShoutDown:
SetDeviceStateToShoutDown();
break ;
case DeviceStatesEnum.ShoutingDown:
SetDeviceStateToShoutingDown();
break ;
case DeviceStatesEnum.StartRunning:
SetDeviceStateToStartRunning();
break ;
}
}

public DeviceStatesEnum GetDeviceState()
{
return _currentDeviceState;
}

private void SetDeviceStateToStartRunning()
{
if (_currentDeviceState == DeviceStatesEnum.Ready)
_currentDeviceState = DeviceStatesEnum.StartRunning;
}

private void SetDeviceStateToShoutingDown()
{
_currentDeviceState = DeviceStatesEnum.ShoutingDown;
}

private void SetDeviceStateToShoutDown()
{
_currentDeviceState = DeviceStatesEnum.ShoutDown;
}

private void SetDeviceStateToRunning()
{
if (_currentDeviceState == DeviceStatesEnum.StartRunning )
{
_currentDeviceState = DeviceStatesEnum.Running;
}
}

private void SetDeviceStateToReady()
{
if (_currentDeviceState == DeviceStatesEnum.Equilibrating )
{
_currentDeviceState = DeviceStatesEnum.Ready;
}
}

private void SetDeviceStateToPowerUp()
{
if (_currentDeviceState != DeviceStatesEnum.Error)
_currentDeviceState = DeviceStatesEnum.PowerUp;
}

private void SetDeviceStateToInactive()
{
if (_currentDeviceState != DeviceStatesEnum.Error)
_currentDeviceState = DeviceStatesEnum.Inactive;
}

private void SetDeviceStateToError()
{
_currentDeviceState = DeviceStatesEnum.Error;
}

private void SetDeviceStateToEquilibrating()
{
if (_currentDeviceState == DeviceStatesEnum.Active)
{
_currentDeviceState = DeviceStatesEnum.Equilibrating;
}
}

private void SetDeviceStateToActive()
{
if (_currentDeviceState != DeviceStatesEnum.Error)
{
_currentDeviceState = DeviceStatesEnum.Active;
}
}
}

Since you have 14 states, you will end up having a Cyclomatic complexity more than 14. Here is the way to reduce this complexity to 1. Do the following changes in the above class DeviceController . Declare a Dictionary .

private
 Dictionary<DeviceStatesEnum, Action> _deviceStateHandler = 
new Dictionary<DeviceStatesEnum, Action>();

Add a constructor to create a mapping with the states.

public
 DeviceController()
{
_deviceStateHandler.Add(DeviceStatesEnum.Active, new Action(SetDeviceStateToActive));
_deviceStateHandler.Add(DeviceStatesEnum.Equilibrating,
new Action(SetDeviceStateToEquilibrating));
_deviceStateHandler.Add(DeviceStatesEnum.Error, new Action(SetDeviceStateToError));
_deviceStateHandler.Add(DeviceStatesEnum.Inactive,
new Action(SetDeviceStateToInactive));
_deviceStateHandler.Add(DeviceStatesEnum.PowerUp, new Action(SetDeviceStateToPowerUp));
_deviceStateHandler.Add(DeviceStatesEnum.Ready, new Action(SetDeviceStateToReady));
_deviceStateHandler.Add(DeviceStatesEnum.Running, new Action(SetDeviceStateToRunning));
_deviceStateHandler.Add(DeviceStatesEnum.ShoutDown,
new Action(SetDeviceStateToShoutDown));
_deviceStateHandler.Add(DeviceStatesEnum.ShoutingDown,
new Action(SetDeviceStateToShoutingDown));
_deviceStateHandler.Add(DeviceStatesEnum.StartRunning,
new Action(SetDeviceStateToActive));

// TODO
// Create mapping for all the states
}

Then, change the ChangeDeviceState as below:

public
 void
 ChangeDeviceState(DeviceStatesEnum deviceState)
{
_deviceStateHandler[deviceState].Invoke();
}

Now the Cyclomatic complexity of the method ChangeDeviceState is one.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

rajeshjj

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值