Saturday, March 24, 2012

My programming tidbits – Clear Code

 

Hi All,

I know I didn’t write a full post for quite a while. I was quite busy with work and other personal issues but I assure you that I am working on something interesting for the next full post. Meanwhile, I will start a series of short posts where I describe my programming tidbits. I will try to write something different than the regular “Write tests! Don’t write long methods! Don’t use the mouse!” that you can read anywhere online. My number 1 tip is this (and if you are going to skip all the other tips, please still consider this one):

Write code that is clear for all the team members.

I will start with an example. I was sent a piece of code for code review which is similar to this one:

  1. public string Foo()
  2. {
  3.   string fileName = Path.GetTempFileName();
  4.   Func<string> func = () => { return Path.Combine(Directory.GetCurrentDirectory(), fileName); };
  5.  
  6.   string fullFileName = func();
  7.   while (!File.Exists(fullFileName))
  8.   {
  9.     fileName = Path.GetTempFileName();
  10.     fullFileName = func();
  11.   }
  12.  
  13.   return fullFileName;
  14. }

This code generates an inexistent temporary file name in the current directory. I kindly asked to change the code to the following:

  1. public string Foo2()
  2. {
  3.   string fullFileName;
  4.   do
  5.   {
  6.     fullFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.GetTempFileName());
  7.   }
  8.   while (!File.Exists(fullFileName));
  9.  
  10.   return fullFileName;
  11. }

After a short argument it was agreed that my code is slightly better in terms of readability (lets leave the performance considerations aside for this example). The main reason that initially this was not the code is because the engineer who wrote the code doesn’t like the do-while loop. To tell the truth, I don’t like do-while loop either. There is something not natural about its flow but in this case it saves a lambda expression, generation and allocation of a new class, and some readability.

When writing code please remember that not all your team members know everything you know. Some might not know lambda expressions well while others might not be familiar with the syntax of LINQ, some don’t like using “var” everywhere while others don’t want to clear unused “using”s because then they miss fundamental system namespaces by default. I am not saying you should not use these advanced framework features. I am saying you should not abuse these features (as in the above example). Think of the poor programmer that has to understand the entire logic of your algorithm and then he sees this method. He may not be best friends with lambdas but now he has to understand what this method does and why the hell did you not use a simple do-while loop instead.

My conclusion: Use advanced language features when they bring benefit to the code and not in order to make your code look cool.

 

Thanks for reading,

Boris.

 

P.S.

If the person who sent this code to me is reading this. Please don’t take this personally, this is just a good example of my tip.

2 comments:

  1. The first version is a terrible style. One needs to understand quite well closures, that you are using the variable, not the value.

    Even the principal developer of C# agrees that it is very confusing, and he is going to change it: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

    In other languages this is not always the case. For example, in Matlab the closure for primitive types is over values.

    ReplyDelete