Friday, September 26, 2008

Returning the comparison results

Over the last couple weeks I have been looking at some of my old code as well as going over other peoples projects. A personal pet peeve of mine keeps popping up in the code the worst part is when I started out programming I did the same thing. It’s when you do a Boolean comparison then return true or false rather than just returning the results of the comparison. Below is an example of what I am talking about.

   21 if (foo == otherFoo)
   22 {
   23     return true;
   24 }
   25 else
   26 {
   27     return false;
   28 }


The above is an example of what not to do. There have been many times in my life where I have done this not thinking about what I was doing. I am glad to say that time has passed. I have talked to others about it and they say they do it because it is more explicit and easier to read. I have a hard time agreeing with this stance how can the above be easier to read then the following.


   21 return foo == otherFoo;  


It’s short simple and easy to read.

Friday, September 19, 2008

Adding unique items to a list the fun way


In some of the work I do I have to combine several lists into one list and only add a item if it is unique by some arbitrary rule. I have done this so often in the last month I was about to write a code snipit for it. Then I started learning about template functions and realized I could just make one function to do this for me. I started out using Contains(vale,IEqualityComparer<>) to see if the item was already in a list this was a lot of effort and I never did figure out how to make a IEqualityCompare delegate. But there is this nice little method on lists called Exists which takes a predicate for comparisone. Which solved all my problems. The extention function I came up with seen below is probaly my favrite so far.

36 public static void AddIfUnique<T>(this List<T> tList, T toInsert, Func<T,T,bool> func)
37 {
38    if (!tList.Exists(p => func(p,toInsert)))
39    {
40        tList.Add(toInsert);
41    }
42 }


The usage for it is as follows.

15 DirectoryInfo mainDir = new DirectoryInfo(@"c:\");
16 List<FileSystemInfo> item = new List<FileSystemInfo>();
17 item.AddRange(mainDir.GetFiles());
18 DirectoryInfo mainDir2 = new DirectoryInfo(@"e:\");
19 List<FileSystemInfo> tList = new List<FileSystemInfo>();
20 tList.AddRange(mainDir2.GetFiles());
21 tList.ForEach(c => item.AddIfUnique(c, (k, j) => k.Name == j.Name));

In the above code the item list will end up with all file names that are unique. While this example is not the most useful example out there it does show how it works.

Tuesday, September 16, 2008

ForEach the functional way.


Before I started my current job I worked as a software tester and did a lot of automated testing in python. I love working in python it takes most of the effort out of programming you just write down what you want and it compiles and runs. Down side is python is not a strongly typed language and I picked up some very bad habits form python. Which others have proceeded to beat out of me. One thing that python did have that I truly miss is the map function. It makes working on lists so much cleaner, and when you mix that with lambda you come out being able to do a lot of work in very few lines of code. A couple weeks ago I was talking with a friend of mine about how C# had no map functions and how if I had it I could shrink a bunch of code down to next to nothing. The following functions are the results of that conversation. At the time I didn't want to return a list at the time I was doing a lot of file maintenance and just wanted to traverse the folder structures in a clean way. So llama being the guy he is emailed me these two functions.

12 public static void ForEach<T>(this IEnumerable<T> list, Action<T> func)
13 {
14     foreach (T t in list)
15     {
16         func(t);
17     }
18 }
19 
20 public static void ForEach<T>(this IEnumerable<T> list, Action<T> func1, Action<T, Action<T>> func2)
21 {
22     foreach (T t in list)
23     {
24         func2(t, func1);
25     }
26 }

Here is an example of how they can be used.

14 public static void WalkFiles(string filePath, Action<string> workerFunc)
15 {
16     if (WalkFilesCont)
17     {
18         if (Directory.Exists(filePath))
19         {
20             System.IO.Directory.GetFiles(filePath).ForEach(workerFunc);
21             System.IO.Directory.GetDirectories(filePath).ForEach(workerFunc, WalkFiles);
22         }
23     }
24 }

I use them in a lot of other areas I even have one variation that behaves like a map in python I don't do much work on lists though where I need to see a result passed back so it doesn't get as much use. These first function gets used quite a bit more than I expected.

Thursday, September 11, 2008

Programming the hard way


On several occasions in my short life I have ran across coders that insist on not using the prebuilt classes and functions that come with .net. I can understand not using a 3rd party lib when you write the entire product for the ground up, but if you are using .net you might as well use it to its fullest extent.
Take the following code:

 9    using (FileStream fs = new FileStream(FilePath, FileMode.Open))
10    {
11        using (BinaryReader br = new BinaryReader(fs))
12            rawTiffData = br.ReadBytes((int)fs.Length);
13    }
14    tiffData = Convert.ToBase64String(rawTiffData);
15 
16    string name = tiffPath.Substring(tiffPath.LastIndexOf('\\') + 1,
17        tiffPath.LastIndexOf('.') - tiffPath.LastIndexOf('\\') - 1);

It will open up a tiff file and read in all of the bytes and then convert it to base 64 encoding. Then he gets the name of the file without its extension. Let's do the same thing but using the .Net functions that should be used.

 9    rawTiffData = File.ReadAllBytes(this.FilePath);
10    tiffData = Convert.ToBase64String(rawTiffData);
11    string name = Path.GetFileNameWithoutExtension(this.FilePath);


The second section of code is almost self documenting. You can at a glance see what is going where and why. You also don't have to worry about getting your substring wrong or someone a year down the road coming in and making a small change to the substring call to make it better. Adding a bug that is not trivial to find.

Wednesday, September 10, 2008

Good code layout.

Recently I have been looking at and writing a lot of c# code. It's nice when you get paid to program in the language you want to learn. I have noticed in several places where people build the same complete object with one or two difference in two separate locations in the code usually a if else statement. I have a big belief in don't repeat yourself when programming. If you find you are writing the exact same code or close to it over and over again you are doing something wrong. Here is a good example of what I am talking about. It also isn't too far from the code that made me want to write this post.



String Foo1 = "3.4.5";
String Foo2= "3.4.6";
mObject boo = null;
if(new Version(Foo1) > new Version(Foo2))
{
    boo = new mObject
    {
        vLam = "yummy",
        jArp= "jello",
        cFile= "No"
    };
}
Else
{
    boo = new mObject
    {
        vLam = "yummy",
        jArp= "jam",
        cFile= "Yes"
    };
}

In the above code we see an example of what not to do. You are creating dynamic objects to make a decision that could be made using a string comparison operator which isn't really on topic but is worth mentioning. Also you have double the code you need in creating your object.


Now let's do it in the cleaner way that I would like to see one instantiation and then just assign the values as we go.



String Foo1 = "3.4.5";
String Foo2= "3.4.6";
bool isFoo2Less = Foo1.CompareTo(Foo2) > 0
mObject boo = new mObject
{
    vLam = "yummy",
    jArp= (isFoo2Less)? "jello" : "jam",
    cFile=(isFoo2Less)? "No" : "Yes"
};

We end up with less lines of code and even though we add a variable to the mix and do two checks. The maintainability of this code is much easier and will cause less confusion over the life of the program.