Mapping with Dictionary instead Switch
Recently I read the book “Refactoring: Improving the Design of Existing Code (2nd Edition)” by Martin Fowler (here…). A great book I highly recommend. Besides a lot of other useful informations and tips I started adapting to not use switch statements for mapping-logic.
Why not using Switch?
The point is that a switch statement can do a lot more things then just mapping value. From my own experience I can confirm that regularly a switch’s case branch does more then one thing. More then just map value A to B. This leads in side-effects of the mapping logic. Further more the code does not clearly show its intent anymore, is harder to read, refactor and extend.
So we look for a better solution for mapping values. A solution that does only map values from A to B and no other logic can be placed into. It should show clearly that it only does a simple value-mapping.
That’s where dictionaries come into the play.
Dictionaries
Dictionary is a collection data-stucture that host key-value items. One can access values very fast by its indexer; the key. They have an optimized and short syntax to do exactly this. If you don’t use delegates as the value you can not add logic. Its a simple value translation table. So the intent should be very clear.
Example
Let’s map an enum value to a string (can be anything else). Here is the enum:
public enum Gender
{
Female,
Male,
Other
}
Map value using a switch statement:
string MapGenderToString(Gender gender)
{
swtich (gender)
{
case Gender.Female:
return "Woman";
case Gender.Male:
return "Man";
case Gender.Other:
return "Other";
default:
throw new ArggumentRangeException();
}
}
The problem here is that you can easily add any kind of logic (code) within one or more case blocks. This would be a code-smell as written before.
Map value using a dictionary:
string MapGenderToString(Gender gender)
{
var mapping = new Dictionary<Gender, string>
{
{ Gender.Female, "Woman" },
{ Gender.Male, "Man" },
{ Gender.Other, "Other" }
}
return mapping[gender];
}
It’s way harder – but not impossible – to missuse this mapping code.
Bonus value: Because the mapping is so simple one whould not even need an extra method for this. The mapping could be defined as a readonly-field and used directly in the parent code.
class PersonMapper
{
private readonly genderMapping = new Dictionary<Gender, string>
{
{ Gender.Female, "Woman" },
{ Gender.Male, "Man" },
{ Gender.Other, "Other" }
}
public PersonDto MapPerson(Person person) =>
new PersonDto
{
...
Gender: genderMapping[person.Gender],
...
}
}
Hope this gives some inspiration. Let me know what you think about this.
Categories
nice blog post! i think its a good alternative to the switch statement!
LikeLike
Great idea – immediately could use it.
Using a DI like autofac, we manage to have a factory based on keyed registrations.
LikeLike
“the code does not clearly show its intent anymore, is harder to read, refactor and extend.”
What about the “switch operator”, though?
LikeLike