Archives for : May2009

Developer Fatigue?

In the recent Visual Studio magazine I saw the following survey:

Do you sense developer fatigue due to the pace of Microsoft Technology introductions?
Yes, some fatigue 45%
No, little or no fatigue 26%
Yes, significant fatigue 24%
Don’t know 5%

(I love kicking it ol’school and using tables)

To the 26% that said no I say, “Good, you’re doing your job.” To the rest of you, “Get to work.”

I don’t often write opinion pieces preferring to keep the focus of this blog more on tutorial type posts, maybe because I don’t really consider myself any real authority. I do my job and in the course of my job I learn a lot that I want to pass on to other people.

So why start now? Well, this survey struck a nerve for me. Maybe it’s because this has some fingers in my post about Oracle and Java. In that post I reveled in the fact that Microsoft is able to keep the .Net framework moving forward at a fast pace and that, relative to .Net, Java has become fairly stagnant.

In Jeff Atwood’s post, The Two Types of Programmers he discusses the two types of programmers as mentioned in an article by Ben Collins-Sussman which says there are two classes of programmers, the “20%” and the “80%” programmers.

To this I have a serious problem. I spend a great deal of time reading the latest programming books, blogs and magazines. I do so because I want to stay current in my field. If I was doctor it would be expected that I would stay up-to-date on the latest research and trends in the medical fields. So should we as programmers.

Our job is to be the best programmers we can be. Fatigue should be irrelevant. Even if you are working in a world were the language features and APIs aren’t moving forward there is still a lot you can do. Read up on patterns and anti-patterns, if you haven’t read Code Complete, do so. I find the idea that programmers are perfectly happy to rest on their laurels completely ridiculous. Strive to become a better programmer, push yourself and your knowledge. As you become better at your job you will become a better person all-around. Knowledge is power.

If you stay current fatigue isn’t an issue. By keeping current incrementally there won’t be any fatigue. Start reading up on .Net 4.0 right now. By the time .Net 4.0 releases you will be pretty caught up and boom!, no more fatigue.

You may say, “Well, my job is to use this or that API or SDK. Knowing anything outside of that is irrelevant.” To that I’m calling “Bullshit!” It’s not about just writing code. If being a programmer was just about writing code then anybody could be a programmer. Writing code is easy. Writing code cleanly, efficiently so it’s easy to maintain, now that takes some skill. The best way to do so is to stay current.

Saying that you’re experiencing “fatigue due to the pace of Microsoft Technology introductions” is a serious cop-out. Staying current is your job because the more current you are the better programmer you are. If I was a fry-cook I’d want to be the best damn fry-cook on the planet, learn the lingo, find the right temperature for the grill so it cooks the eggs and burgers efficiently, work on recipes that taste good and can cook fast. I’m not a fry-cook, however, I’m a computer programmer. Being the best programmer I can be means that I have to stay current on new technology. Screw fatigue.

Thank you, that’s my time

high-pitched whine as I drop the microphone

As I’m sure you can tell by the title of this post that it is about deferred execution in LINQ. When a LINQ query (I know, it’s like saying, “NIC card” or “ATM machine”) is created the values are not immediatly determined. Only when the list is utilized are the results determined.

This bit me at first so hopefully with this it won’t bite you.

If you have:

List<Product> products = new List<Product>();
products.Add(new Product { Id = 1, Name = "Cheese", Quantity = 2 });
products.Add(new Product { Id = 2, Name = "Wine", Quantity = 2 });
products.Add(new Product { Id = 3, Name = "Crackers", Quantity = 0 });

var zeroInStock = from product in products
                  where product.Quantity == 0
                  select product;

foreach (var stock in zeroInStock)
{
    products.Remove(stock);
}

you will get:

InvalidOperationException was unhandled. Collection was modified; enumeration operation may not execute.

This is due to the deferred execution of LINQ. The results of zeroInStock are not calculated until you need them. The problem is that if you attempt to remove an item from the list in which the result originated from the original list is now not valid for the LINQ query. So how do you combat this? With ToList(), ToArray() and ToDictionary().

List<Product> products = new List<Product>();
products.Add(new Product { Id = 1, Name = "Cheese", Quantity = 2 });
products.Add(new Product { Id = 2, Name = "Wine", Quantity = 2 });
products.Add(new Product { Id = 3, Name = "Crackers", Quantity = 0 });

var zeroInStock = (from product in products
                  where product.Quantity == 0
                  select product).ToList();

foreach (var stock in zeroInStock)
{
    products.Remove(stock);
}

Now this code works. In this example ToList() and ToArray() could have been used interchangbly since we’re utilizing var but you may need one over the other. By calling ToList() or ToArray() it forces execution of the query. This means that now you can change the original list all you want without any issues.

ToDictionary() works a bit different. You have to specify a lambda expression to detemine what the key should be for each given result. Here’s the ToDictionary() example:

List<Product> products = new List<Product>();
products.Add(new Product { Id = 1, Name = "Cheese", Quantity = 2 });
products.Add(new Product { Id = 2, Name = "Wine", Quantity = 2 });
products.Add(new Product { Id = 3, Name = "Crackers", Quantity = 0 });

var zeroInStock = (from product in products
                  where product.Quantity == 0
                  select product.ToDictionary(x => x.Name);

foreach (var stock in zeroInStock)
{
    products.Remove(stock.Value);
}

You can see here the lambda expression means that the generated dictionary will be made of KeyValuePair<string, Product>. Since the product is now the value of the KeyValuePair the foreach that removes products with zero in stock now uses the Value.

If you are going from dictionary to dictionary as in:

Dictionary<int, Product> products = new Dictionary<int, Product>();
products.Add(1, new Product { Id = 1, Name = "Cheese", Quantity = 2 });
products.Add(2, new Product { Id = 2, Name = "Wine", Quantity = 2 });
products.Add(3, new Product { Id = 3, Name = "Crackers", Quantity = 0 });

var zeroInStock = (from product in products
                   where product.Value.Quantity == 0
                   select product).ToDictionary(x => x.Key);

foreach (var stock in zeroInStock)
{
    products.Remove(stock.Key);
}

you will most likely want to just use the existing key as I have above. Now, this doesn’t mean you can’t change the key but for my purposes I just used the existing key since I can use that to just remove from the dictionary.

That’s all for now. Leave me a comment if you have any questions.

Brian