Using Dictionaries to refactor
Tails128
Posted on May 18, 2020
About one year and a half ago, I joined an awesome team of developers which had set up a very efficient environment from which I have learned a lot.
One of the many ideas which arose in such a thriving environment is to use Dictionaries as configuration files. In order to explain what I mean, and let's start from some bad code:
switch(foo.fooType) {
case fooType.a: {
bar(anEnum.aValue, foo, true);
}
case fooType.b: {
bar(anEnum.bValue, foo, true);
}
case fooType.c: {
bar(anEnum.cValue, foo, true);
}
default: {
throw new ArgumentOutOfRangeException();
}
}
Just by looking at this code it looks like it is very complex: in the switch
we are calling a function depending on foo
... but this is not true!
What is actually happening is that we are just configuring the first parameter (anEnum
).
Let's fix this
anEnum myValue;
switch(foo.fooType) {
case fooType.a: {
myValue = anEnum.aValue
}
case fooType.b: {
myValue = anEnum.bValue
}
case fooType.c: {
myValue = anEnum.cValue
}
default: {
throw new ArgumentOutOfRangeException();
}
}
bar(myValue, foo, true);
This surely looks more understandable: it is immediate to see that we are not calling different functions, but we are just using a different value for myValue
... but we can improve it a bit more with the use of a Dictionary
.
fooConfigurator.cs:
public static Dictionary<fooType, anEnum> fooConfigurator = new Dictionary<fooType, anEnum>() {
{ fooType.a, anEnum.aValue },
{ fooType.b, anEnum.bValue },
{ fooType.c, anEnum.cValue },
}
ourFile.cs
if(!fooConfigurator.Contains(foo.fooType){
throw new ArgumentOutOfRangeException();
}
anEnum myValue = fooConfigurator.get(foo.fooType);
bar(myValue, foo, true);
This allows for some benefits in our code:
- O(1) access time instead of O(n) if you are using interpreted languages (partially compiled languages as java or c# and compiled languages usually adopt access tables, making it already O(1)... compilers are awesome!)
- The code is more readable: we can clearly see we just configure
myValue
depending onfoo.fooType
, and nothing else. - This allows for simple configuration by updating our dictionary.
Can we do more with dictionaries?
Sure!
The cool thing about using Dictionaries
as configuration files is that, if you use it with care, you can also pass functions or multiple parameters (just use objects) with a dictionary, allowing for a lot of flexibility!
What do you think about this approach? Let me know in the comments!
Posted on May 18, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.