I’m starting a new series here: Fun with C#! The idea is to post a couple of things I do in this cool language. 🙂
When I talk about Clean Code with developers, an example that I always use is switch-blocks. Every bad code out there always features abusive use of switch-blocks. In most cases, those blocks start off very simple, with one-liners, like the sample below:
public void DoStuff(DayOfTheWeek dayOfTheWeek) { switch (dayOfTheWeek) { case DayOfTheWeek.Sunday: Console.WriteLine("Do stuff for Sunday..."); break; case DayOfTheWeek.Monday: Console.WriteLine("Do stuff for Monday..."); break; case DayOfTheWeek.Tuesday: Console.WriteLine("Do stuff for Tuesday..."); break; case DayOfTheWeek.Wednesday: Console.WriteLine("Do stuff for Wednesday..."); break; case DayOfTheWeek.Thursday: Console.WriteLine("Do stuff for Thursday..."); break; case DayOfTheWeek.Friday: Console.WriteLine("Do stuff for Friday..."); break; case DayOfTheWeek.Saturday: Console.WriteLine("Do stuff for Saturday..."); break; } }
It always start off simple like that. Next thing you know, there’s another “simple change” that comes in, and now the code looks somewhat like this:
public void DoStuff(DayOfTheWeek dayOfTheWeek, TimeOfTheDay timeOfTheDay) { switch (dayOfTheWeek) { case DayOfTheWeek.Sunday: Console.WriteLine("Do stuff for Sunday..."); if (timeOfTheDay == TimeOfTheDay.Evening) { Console.WriteLine("Go to bed early!"); } break; ... case DayOfTheWeek.Saturday: if (timeOfTheDay == TimeOfTheDay.Morning) { Console.WriteLine("You may stay a little longer in bed..."); } else { Console.WriteLine("Do stuff for Saturday..."); } break; } }
Then comes an if-else, a for-loop, a switch-block (yes, inside the other switch, of course), and that one method becomes a terrible mess.
Well, whenever I see a case like that, I consider changing the switch-block into a dictionary of actions. I populate a dictionary with the individual blocks of code I need executed, and then I get the delegate out of the dictionary and invoke it whenever needed. The updated code would look like this:
readonly Dictionary<DayOfTheWeek, Action<TimeOfTheDay>> _dailyActions =
new Dictionary<DayOfTheWeek, Action<TimeOfTheDay>>();public FamousSwitch()
{
_dailyActions.Add(DayOfTheWeek.Sunday, DoSunday());
_dailyActions.Add(DayOfTheWeek.Monday, DoMonday());
_dailyActions.Add(DayOfTheWeek.Tuesday, DoTuesday());
_dailyActions.Add(DayOfTheWeek.Wednesday, DoWednesday());
_dailyActions.Add(DayOfTheWeek.Thursday, DoThursday());
_dailyActions.Add(DayOfTheWeek.Friday, DoFriday());
_dailyActions.Add(DayOfTheWeek.Saturday, DoSaturday());
}Action<TimeOfTheDay> DoSaturday()
{
return timeOfTheDay =>
{
if (timeOfTheDay == TimeOfTheDay.Morning)
{
Console.WriteLine("You may stay a little longer in bed...");
}
else
{
Console.WriteLine("Do stuff for Saturday...");
}
};
}Action<TimeOfTheDay> DoFriday()
{
return timeOfTheDay => Console.WriteLine("Do stuff for Friday...");
}Action<TimeOfTheDay> DoThursday()
{
return timeOfTheDay => Console.WriteLine("Do stuff for Thursday...");
}Action<TimeOfTheDay> DoWednesday()
{
return timeOfTheDay => Console.WriteLine("Do stuff for Wednesday...");
}Action<TimeOfTheDay> DoTuesday()
{
return timeOfTheDay => Console.WriteLine("Do stuff for Tuesday...");
}Action<TimeOfTheDay> DoMonday()
{
return timeOfTheDay => Console.WriteLine("Do stuff for Monday...");
}Action<TimeOfTheDay> DoSunday()
{
return timeOfTheDay =>
{
Console.WriteLine("Do stuff for Sunday...");
if (timeOfTheDay == TimeOfTheDay.Evening)
{
Console.WriteLine("Go to bed early!");
}
};
}public void DoStuff(DayOfTheWeek dayOfTheWeek)
{
_dailyActions[dayOfTheWeek].Invoke(TimeOfTheDay.Morning);
}
I like keeping the smaller individual methods for each operation. Most often than not, I’ll end up moving those separate methods into one separate class, and very often, will turn that one separate class into several separate classes.
Anyway…
- I like using a dictionary of delegates instead of using switch-blocks;
- I like having small methods a lot better than having one long method