65.9K
CodeProject is changing. Read more.
Home

Reducing Code Complexity on Switch-blocks

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (49 votes)

Oct 7, 2008

CPOL

2 min read

viewsIcon

121637

Using a Dictionary instead of a switch-case construction to reduce complexity and increase testability

Introduction

A switch-block becomes complex very easily. All code is placed in one method and parts of it are used multiple times. In a lot of cases, a switch-block is based on an enum. Next to that, it's not possible to use a fall-through in C#. The only way to go from case to case is the use of the goto statement, which isn't a good idea when reducing complexity. Although I've written the examples in C#, it wouldn't be hard to apply the principles to other languages.

A Solution

A nice solution to get rid of large switch constructions is the use of a Dictionary<enum,delegate>. This way every element of the enum can be attached to a method. It is possible to call the right method for every enum possible. Because every enum has its own method, it's very easy to use this construction in a testdriven environment. Another nice thing is that it's no problem to call one method from another. Let me explain a little further with an example and some pseudo code. Imagine a program that prepares food. This part contains the recipes.

Let us start with the following enum:

Enum food{
    Apple,
    ApplePie,
    AppleJuice,
    Pizza
}

It's not hard to imagine that all of the foods need a specific preparation, but that some actions need to be done for different foods, like peeling an apple or baking in the oven.

To add the preparations to the Dictionary<enum, delegate>, we first need to define a delegate method:

delegate bool Preperation();

Now we need to define the actual preparation methods for every item of the enum, making sure they're declared the same way as the delegate, thus the same parameters and return value. The method returns a boolean when preparation is successful.

In this example, the methods may look something like this:

bool PeelApple()
{
	// code to remove peel
	return true;
}
bool BakePie()
{
	PreheatOven(180.0);
	PeelApple();
	CreatePie();
	while(!doneBaking())
		Bake();
	return true;
}
bool MakeAppleJuice()
{
	PeelApple();
	Juicify();
	return true;
}
bool BakePizza()
{
	PreheatOven(160.0);
	CreatePizza();
	while(!doneBaking())
		Bake();
	return true;
}

Notice that BakePie() and MakeAppleJuice() both call the method PeelApple(). This is not possible in a switch – case constructor, unless you call the methods from each case.

Now all that's left is to create and initialize the Dictionary.

Dictionary FoodPreperation;
..
FoodPreperation = new Dictionary<food, Preperation>();
FoodPreperation.add(food.Apple, new Preperation(PeelApple));
FoodPreperation.add(food.ApplePie, new Preperation(BakePie));
FoodPreperation.add(food.AppleJuice, new Preperation(MakeAppleJuice));
FoodPreperation.add(food.Pizza, new Preperation(BakePizza));

Calling the methods is done by:

food FoodOfChoice = food.ApplePie;
FoodPreperation[FoodOfChoice]();

In the last code snippet, the method that goes with food.ApplePie is executed.

History

  • 07 Oct 2008 - Initial upload