Tuesday, November 22, 2005

Quote of the Day

Unfortunately, I'm forced to agree:

"Programmers have huge and fragile egos."

- Philip Greenspun, MIT Professor
From his article "Managing Software Engineers"

Friday, November 11, 2005

Veteran's Day Code


foreach (Soldier thisSoldier in US.Population)
{
ThankSoldier(thisSoldier, DateTime.Now());
}

Monday, November 07, 2005

Speeding Up MSDN Downloads

I normally try to avoid regurgitating other peoples' posts, but in this case I'll make an exception (System.PlagerismException?) because the information is so valueable. We actually use this technique with great success where I work, but I'll cite the blog the started it all:

If you're an MSDN subscriber and have ever tried to download a huge set of files, I'm sure you know how long it can take when you're only getting about 25kbps speed from Microsoft's MSDN Subscriber Downloads. The problem is, you may be hitting a non-US mirror site. So, here's a way to speed things up a bit.

In the hosts file on the machine doing the downloading (%windir%\system32\drivers\etc\hosts) add an entry for the Microsoft server:
207.46.252.185 global.ds.microsoft.com

Then, in Internet Explorer, add https://global.ds.microsoft.com in the list of trusted sites under Tools > Internet Options > Security > Trusted Sites. Also, under the privacy tab click the 'Sites' button and enter https://global.ds.microsoft.com so that microsoft.com is a trusted domain.

We did this at work and saw a speed increase from about 25kbps to ~150kbps.

Source: Jason Mauss' Blog Cabin

Saturday, November 05, 2005

Comments

Okay, I realize this is a techie blog, so there should be some technical meaning to this post. Accordingly, I'll post my thoughts on commenting the code you write.



The real reason for this post, however, is mostly to point out that I've turned the comment feature back on for this blog. As I pointed out in a post to my personal blog, Blog*Spot had some trouble with spam. It seems to be all better now, and I've had the commented turned on in my other blogs with no trouble for more than a week now.



Back to the relevant topic: comments. Developers have been arguing for years over what should be commented, and what shouldn't be. The rule of thumb I use is that the code itself should tell the what, not the comments. If you can't look at the code and easily determine what it's doing, you need to refactor it.



So then, what are comments for? The comments should tell the why. That's my rule of thumb: the code tells the what, the comments tell the why.



Maybe you wrote some code that deletes a file. The what will be fairly obvious. But why are you deleting this particular file? Here's an example:



In C#, you can also include XML comments. Visual Studio will automatically create an XML comment stub for you if you type 3 comment slashes (///) immediately preceeding a method, or other commentable element. (Note that there are several 3rd party add-ins that allow you to auto-create XML comments in Visual Basic).



When you're finished, it looks something like this:



XML comments are exceptionally useful, and I recommend them highly. First, they remove the need for those painful block comment headers that some companies require. You know the ones - they have such important information as the programmer's name and the date the method was written (because nothing will help me debug like knowing that something was written 3 months ago).



If you specify a file path in your project properties, Visual Studio will create an XML file of all the comments for you during compilation. To set this up, set the XML Documentation File in build section under Configuration Properties from the project properties window as in the following example:




If you create an XML, then a snazzy tool like NDoc will pick up the file, use a little reflection, and create an instanct CHM help file to document your code. Viola! Instant documentation. Few things make a developer happier than not having to waste time writing doc.



Even if you don't plan on creating documentation, there's another reason to use XML commenting. Intellisense looks for it when showing you a method signature. Look what happens when I use the UserHasPermission method from the example above:



This could be extremely helpful if you need to reuse someone else's code, or if somebody needs to use yours.



So the lesson in all this is:
  1. Code tells the what, comments tell the why
  2. Use the XML comments feature of visual studio
  3. I turned the comments back on for this blog, so you can leave some
Happy coding!

Thursday, November 03, 2005

Programming Evolution

The other day I was talking to a friend about how programming has changed in the last 15 years. What used to be required (to be a decent programmer, anyway) was an extreme depth of knowledge. You had to really understand that hardware your apps were running on, and we used to make every effort to optimize for performance, and yes, size.



Fast forward 15 years...



Nowadays, the hardware has been largely abstracted away from most programmers (don't argue - I know there will always be a need for people to write device drivers, and I also understand that the Linux camp thinks they are 1337). It's no longer necessary to squeeze the most out of every byte because, quite frankly, there is plenty of memory and hard drive to spare.



We also have nice GUI development tools that provide slick WYSIWYG interfaces. What used to take hours of painstaking coding in a text editor can now be accomplished literally in minutes via drag-and-drop.



These things considered, is it easier to be a programmer now than it was 15 or so years ago? I don't think so. In fact, I think quite the opposite is true.



While we're not wasting time coding as much stuff by hand, and we don't need quiet the depth of knowledge about the hardware, the breadth of knowledge required to be a decent programmer has increased exponentially.



15 years ago we didn't have to worry about the Internet. Programmers these days not only need to know their core programming language (be it C#, C++, VB, Java, Perl, Python, Ruby, or something else), they also need to understand the Internet. That means having an understanding of the network infrastructure itself, as well as the relevant protocols (TCP, IP, HTTP, FTP, etc).



We need to understand interoperability better than ever before, and we also have to have specific knowledge relative to the challenges of distributed computing. I won't even get into the different database options, and what developers need to know. Clearly, the number of areas in which we all really need to have some level of knowledge, if not specialization, is staggering.



All things considered, I think it's actually a little more difficult to be a modern day Software Engineer. Our predecessors may complain of punch cards, command-line compiling, and text-based development tools, but at least they had enough time to do the work without the tools we enjoy today. It'll be interesting to see how the field changes in the next 15 years.

Wednesday, November 02, 2005

Making a Sortable Collection

Today I needed a collection that would be self-sorting, and I came up with this handy technique for making one. This approach should work for any object that inherits the System.Collections.CollectionBase object.



The key to this approach is that part of the underlying plumbing of the CollectionBase is an ArrayList. Since ArrayLists are self-sorting, wiring this up is a breeze.



The sort method of an ArrayList have a few overloads. One takes no parameters, and the other takes an IComparer object. What does it mean? Well, if you don't specify a comparer object, the array list will be looking to the objects in the collection to perform comparisons against one another as part of the sort aglorithm.



Consider the following example (I like using the good old dog object). Let's say you have a simple "Dog" class that has two properties: Name, and BirthDate. You want to write a collection to store Dog objects, and you need the ability to quickly sort the Dogs in this collection by either name or Birthdate. (Maybe you're writing some kennel software or something - who knows?)



First, a look at the Dog object. It's pretty standard, but you'll notice that it implements IComparer (see my "Implementation and Inheritence Primer" post for more information about this).




public class Dog : IComparable
{
private string _name = string.Empty;
private DateTime _birthDate = new DateTime();

public Dog()
{
//Empty Constructor
}

public Dog(string itemName, DateTime birthDate)
{
_name = itemName;
_birthDate = birthDate;
}

public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}

public DateTime BirthDate
{
get
{
return _birthDate;
}
set
{
_birthDate = value;
}
}

public int CompareTo(object obj)
{
//required by IComparable
if (obj is Dog)
{
Dog temp = (Dog) obj;

return _name.CompareTo(temp.Name);
}
else
{
throw new ArgumentException(
"Object is not a Dog");
}
}
}




You'll notice that as required by the IComparer class, Dog has a public method named "CompareTo". The ArrayList will execute this method when comparing two Dog objects during the sort algorithm.



What about non default sorts? We need a couple of IComparer objects to pass into the ArrayList. Here's some examples of objects that will compare Dog objects by Name or Birthdate:





public class DogNameComparer : IComparer
{
public int Compare(object x, object y)
{
if (x is Dog && y is Dog)
{
Dog dog1 = (Dog) x;
Dog dog2 = (Dog) y;
return dog1.Name.CompareTo(dog2.Name);
}
else
{
throw new ArgumentException(
"Object is not a dog.");
}
}
}






public class DogBirthDateComparer : IComparer
{
public int Compare(object x, object y)
{
if (x is Dog && y is Dog)
{
Dog dog1 = (Dog) x;
Dog dog2 = (Dog) y;

//let the underlying data type do the work:
return dog1.BirthDate.CompareTo(dog2.BirthDate);
}
else
{
throw new ArgumentException("Object is not a Dog");
}
}
}





Now on to that collection. We implement a pretty standard collection, including a couple of handy overloads for the Add method. We also add a "Sort" method to tell our collection to sort itself. Note that the Sort method makes the underlying ArrayList do the heavy lifting.





public class DogCollection : CollectionBase
{
public DogCollection()
{
//Empty Constructor
}

//Add this dog directly to the inner list
//The inner list is an array list, and we'll
//use it for sorting later
public virtual Dog Add()
{
Dog newDog = new Dog();
this.InnerList.Add(newDog);
return newDog;
}

public virtual void Add(Dog dog)
{
this.InnerList.Add(dog);
}

public virtual Dog Add(string name, DateTime birthDate)
{
Dog newDog = new Dog(name, birthDate);
this.InnerList.Add(newDog);
return newDog;
}

public void Sort()
{
//easy as pie - since no sort type was specified,
//the InnerList ArrayList object will use the
// implementation of IComparable built into the
//dog object itself

this.InnerList.Sort();
}

public void Sort(DogSortType type)
{
//since a sort type was specified,
//we'll use one of our Sorter objects
//in conjunction with the array list to
//do the sort

switch (type)
{
case DogSortType.Name:
{
this.InnerList.Sort(new DogNameComparer());
break;
}

case DogSortType.BirthDate:
{
this.InnerList.Sort(new DogBirthDateComparer());
break;
}

default:
{
throw new ArgumentException(
"Unsupported sort type: "
+ type.ToString());
}
}
}
}





And finally, a little bit of enumeration to define the types of sorting allowed:




public enum DogSortType
{
Name,
BirthDate
}




Viola! It's cake.



Watch for updates to this post (there are details I still need to add), but one thing I would point out is to ALWAYS CODE DEFENSIVELY. For example, you'll notice that the methods in these objects don't trust the data passed in - they all test for invalid values, and take appropriate action.



Happy coding!