Comment your code when it is hard to understand or determine your intent, because your code is crap. Yep, that is pretty much the best time to comment your code. When I was in college I was told to make sure that I commented my code. I always wondered why. Now I know. Comments really tended to clutter things and make it less clear what I was trying to achieve. I’ve written plenty of comments, but I know that when I use a comment that it means my code sucks.
Comments take time to write, they take up valuable space, they add clutter, and they’re often out of date. So why do we write them? We write them because there is something confusing about some code. Or something that we need to tell future readers about the code.
I very much enjoy being reassured of the way I do things by the books I read. I’ve been reading Code Complete, and it makes me glad they I blatantly disagreed with the people who told me to comment my code. Why? Because the author of the book tells me the exact opposite. I’ve often used the phrase, “code should be self-documenting.” I am not sure from whom or from where I first heard that, but it also affirmed my belief about comments.
The proper use of comments is to compensate for our failure to express ourself in code. Note that I used the word failure. I meant it. Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration.
Aside from the misuse of the English language, that is an excellent paragraph. I’ve never liked writing comments, and I doubt I ever will. It is interesting how some programmers swear by them. I think they are the same programmers who use single-letter variables, magic numbers, and hundred line methods.
I highly recommend reading through the best comments in source code question on StackOverflow.
Remember kids, anytime you feel the need to write a comment, fix your code instead. You’ll thank yourself down the road. You might be the future developer maintaining the code.
A few steps to follow. (These are the easy ones. Harder ones take more than a bullet point to explain and justify.)
- Rename variables to more expressive names.
- Extract methods so people know what you’re doing.
- Extract classes to handle each responsibility.
Recently I was reading through a bunch of interesting blog posts. I was looking for information about the use of callvirt in C#. Callvirt can be used to call both virtual and non-virtual methods, and in fact is how all methods are called in C#. I don’t know how much of a performance decrease there is based on this, but I doubt it is much of one. I stumbled across this interesting post covering why C# uses callvirt from Eric Gunnerson’s blog.
We had gotten a report from somebody (likely one of the .NET groups using C# (thought it wasn't yet named C# at that time)) who had written code that called a method on a null pointer, but they didn’t get an exception because the method didn’t access any fields (ie “this” was null, but nothing in the method used it). That method then called another method which did use the this point and threw an exception, and a bit of head-scratching ensued. After they figured it out, they sent us a note about it.
We thought that being able to call a method on a null instance was a bit weird. Peter Golde did some testing to see what the perf impact was of always using callvirt, and it was small enough that we decided to make the change.
Now that certainly is odd behavior. I don’t know how I feel about it though. So basically one could have been able to call instance methods on null instances of an object as long as they didn’t access any members of the object itself. First I will say that methods with fewer dependencies are great.
So C# was of course adjusted to disallow this, but if it hadn’t then this could potentially work.
using System;
namespace NullInstanceMethod
{
class Program
{
static void Main(string[] args)
{
Enrick brendan = null;
Console.WriteLine(brendan.Awesome());
}
}
class Enrick
{
public string Awesome()
{
return "Awesome";
}
}
}
Yep, that method isn’t static. It’s an instance method, but you would have been able to call it.
So to see that in action why don’t we disassemble this code and make the change directly to the intermediate language.
First we need to get the IL using ildasm, so open up the VisualStudio 2008 Command Prompt and type this command.
ildasm PathToTheExecutable /out:new.il
This will create a file “new.il” in our VS Command Prompt working directory.
Now we can open this in our favorite editor and we will see a bunch of code. We are just looking at this main method though.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 16 (0x10)
.maxstack 1
.locals init ([0] class NullInstanceMethod.Enrick brendan)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: callvirt instance string NullInstanceMethod.Enrick::Awesome()
IL_0009: call void [mscorlib]System.Console::WriteLine(string)
IL_000e: nop
IL_000f: ret
} // end of method Program::Main
See IL_0004 there is our callvirt that makes the call to our instance method. If we change that to a regular call we should be good.
Now we just put the IL back into the assembly.
And we execute it and here is the result.
And there you have it. I just called an instance method on a null instance of a concrete class without getting a null reference exception? Strange? Yes. Wrong? I don’t know if it really is.
For your homework I would like you to consider what would happen if I were calling an interface’s method instead of a concrete class.
Over the summer, Nimble Pros brought on some new interns. We of course brought them up to speed on how we do things here. We like the integration process of bringing new employees into the mix immediately involving them in the process the entire team is involved with. To help get them up to speed we use a combination of pair-programming, book and article reading, and formal instruction.
As I am sure anyone who uses Visual Studio for web development knows, there are two main ways to go about creating the site that you’re going to develop. There is the web application project (WAP) and the web site (ignoring MVC of course).
Back in the days of ASP.NET 1 there was only one way of doing things, web application projects. ASP.NET 2 got rid of WAPs and replaced them with web sites. Not entirely sure why, but it did not take long before Microsoft added Web Application Projects back into the mix. These were able to be installed and added into Visual Studio so they could be used again.
I of course switched to these as soon as they were readily available. The title of this post kind of gives that away. I switched for a few reasons including the dueling assemblies issue which can occur with web sites. I have written about dueling assemblies and some of the differences between these methods of developing sites before.
The main reason why I prefer having a project is that I like being in control. Now you might wonder how I can have more control with a project file. It might seem that the less controlling approach would give me more control, but it is not the case. The loose collection of files, lovingly referred to as a web site is hard to control. I can’t say what is included I can’t say what is excluded. My only control is the relative locations of files. Inclusion of a library? Oh that is a refresh file in the bin folder.
Sure I can get some control in a web site’s loose structure, but I feel that I get so much more control from the project file. I have something obvious to point MSBuild to. I have settings and targets I can manipulate in the file. I have direct control of which files are in the project. Heck I can control which version of a dll I am using which means no more dueling assemblies. Hooray!
Perhaps you disagree. I prefer the WAP to the web site. Do you have any good reason to think otherwise?
Just like many other developers I know, I have a stack of books I intend to read high enough that I could not hope to finish them ever. I know that the stack will increase in size as fast as I finish the books. I have plenty of technical books I intend to read as well as a large quantity of those which are purely for my own entertainment.
Required Developer Reading
I think it is very important to continue reading and learning to be a better developer. Here at Nimble Pros we make sure that our developers know what they should be reading, so every time we hire someone I make sure that they get there hands on these books. While not required, we highly encourage our developers to take the time to read these excellent books.
Code Complete – This is a classic that is on a lot of reading lists. I read this one a few years ago, and I really think that you should read it if you have not. It is a fairly large book that covers a variety of topics with a great deal of depth and breadth. It really is worth the time and effort to read.
Working Effectively with Legacy Code – While the name of this book is somewhat misleading based on people’s definition of “legacy code”, I still believe this is one of the most important books for every developer to read. Michael C. Feathers wrote an excellent book with this one. Every developer is going to need to work with legacy code constantly during their time as a developer. We don’t always work on green-field projects, and this book takes a hands-on approach to explaining how to deal with and fix up legacy code.
I am Currently Reading
Yesterday, I started reading Clean Code, which is a book I am already fascinated with. I mention this because I believe it will make the above list once I am done reading it. I have only just started reading it, but I’ve already got plenty of notes I’ve taken as I’ve been reading it. I plan on discussing as much as I can about the book and its topic as I read it.
Look forward to some blog posts responding to this great book.
Removing code is one of my favorite activities. Isn’t it one of yours? As a software developer I strive to write less code. Sounds kind of funny, but what I mean is that I want the code that I write to be reused as effectively as possible. Having less code means that maintenance is easier. I can fix things faster, change things faster, find things faster, and figure things out faster.
This is a very good case of “less is more”, which is one reason why I love removing code. I really enjoy getting more or even equivalent work done with less code.
I just finished eliminating a constructor. Why? Well, it really was not needed. As it turns out there was a more appropriate constructor to use for the class. Not sure when or why the constructor was created, but it doesn’t really matter. I am fairly certain that nothing is using it after my removing it. Code still compiles. Tests still pass.
This does a lot of good things. It makes the class less intimidating by dropping the line count. It makes clearer which constructor to use when there are fewer of them. If I need to make a change to the constructor by either adding or removing a parameter for example there is only one place to do this now. Before there were two places.
I love writing code, but I also enjoy removing excess code. It just makes things simpler, which is exactly how I like things. I want my code to be just complex enough to work. When I am refactoring old code this is one of the best things to do. Chopping off all the bits and pieces of unneeded legacy code is progress.
Has anyone else removed any code recently they were glad to be rid of? Anyone eliminate any entire class libraries or anything cool like that?
“Do you want complexity with that?”
“No, thank you.”