[philiptellis] /bb|[^b]{2}/
Never stop Grokking


Saturday, May 17, 2008

Commenting

A discussion at work got into whether comments are good or not. I have my own opinions about comments, and years of having to dig through other people's code has taught me not to trust them too much. Comments that I've put into my code in the past have generally been stories and anecdotes that I wanted to tell future readers of my code, and seldom about the code itself.

When I have to go through someone else's code, I start off by assuming that their comments were bad and delete all but a few of them. They may not actually be bad, but it saves me the time I'd spend separating bad comments from good ones, and I can always refer to the last version in CVS if I need to check on old comments. In general, I've seen the following types of comments:
  1. Useless comments - they explain what a particular piece of code does
  2. Obsolete comments - the code changed but the comments didn't
  3. Mental notes - they explain why a particular piece of code does what it does
  4. Reminders - FIXME/TODO comments
There are also API docs that look like comments, but that's only because the comment syntax in most languages is the only way to add documentation (perl has pod though). I'll ignore this type, but you still need to be careful of API docs that don't match the API or the implementation - they're probably both wrong.

The first type is largely useless. The code is either very obvious in what it does, in which case the comment is not needed, or it's not, in which case it should be rewritten. One of the rules from the Elements of Programming Style goes thus:
Don't comment bad code, rewrite it
It's #63 if you care, while #69 says:
Don't over-comment
The next type is worse than useless, it slows you down in your understanding of the code. Delete and take note of rule #61:
Make sure comments and code agree
The third type of comment is useful in understanding a block of code and the thought process that went into it, and is also useful in knowing how to rewrite/optimise that code. Some developers may prefer to push this kind of comment out to bugzilla and link to it in the code. Either way works. I generally leave these comments around or rewrite them depending on what I'm doing to the code they affect. Rule #62 says:
Don't just echo the code with comments - make every comment count
This is how you make it count.

Reminders, IMO, are better suited to bugzilla with the bug number noted in the code. This is so mainly because bugzilla sends out reminders while your code doesn't. If I can, I'll fix the relevant code, or delete the comment if no longer pertinent (these kinds of comments tend to hang around for several years without anyone noticing).

Oh, and just in case someone wanted to counter #2 by saying that sometimes you need to write obscure code to be efficient, or because it was a smart way to do something, I present to you rules #1, #2 and #5:
Write clearly - don't be too clever
Say what you mean, simply and directly
Write clearly - don't sacrifice clarity for "efficiency"
So, have fun commenting your code, have a dialogue with your readers, or think of it as a mini blog about the code, but make sure you make your comments useful or fun. If you're interested in the quick summary of the Elements of Programming Style, grab the fortune cookie file.

Wednesday, April 23, 2008

strftime in Javascript

As a follow-up to my last post about Javascript date functions, I went ahead and implemented strftime for javascript.

Have a look at the demo at the link above, and download the code: strftime.js. It's distributed under a BSD license, so use it and give me feedback. Post comments here for now.The code is documented using doxygen style comments.

You should also check out Stoyan's time input library that lets you do the equivalent of php's strtotime function.

Update: This code is now part of the YUI library and all further development will be done there.

Tuesday, April 22, 2008

Javascript date functions

I keep forgetting what I can do with dates in javascript, so this post is just a list of built in date functions. I've also seen a lot of sites that do some terrible things with javascript dates including trying to parse it out of a string, or using getYear(). Don't do that.

I've also seen sites that contain arrays of calendar month names and days of the week. This is locale specific, so do it only if you're willing to make the array easily localised.

To create a new date object:
var d = new Date;

var d = new Date('2008/04/22');

var d = new Date('2008/04/22 01:03:31');

var d = new Date(1208758100000);
Note: don't type that into firefox/firebug while editing a post on blogger - they have a global variable called d which is used to save your post.

Also don't forget the new keyword. Without that you'll just create a string containing the current date.

After this line, d evaluates to a string representation of the date which isn't very useful for anything since it's almost always not what you want. You really want to get various parts of the date out. There's a whole bunch of functions to do that:
d.getYear();         // deprecated function to get year.  don't use this
d.getFullYear();     // get four digit year.  use this
d.getMonth();        // get the month 0 - 11
d.getDate();         // get the day of the month 1 - 31
d.getDay();          // get the day of the week 0-6 (Sunday is 0)
d.getHours();        // get the hour - 0-23.  Note the s in the function name
d.getMinutes();      // get the minutes of the hour - 0-59
d.getSeconds();      // get the seconds of the minute - 0-59
d.getMilliseconds(); // get milliseconds past the second - 0-999
d.getTime();         // get number of milliseconds since the epoch.  integer divide by 1000 to get unix timestamp
d.getTimezoneOffset(); // get offset from GMT in minutes - note capitalisation
All of these functions return the value for your current timezone. To get values in UTC, add UTC after the get in the method name. There are also equivalent set methods, but I've never needed to use them.

One useful method is parse() which takes in a string representation of a date and returns the number of milliseconds since the epoch for that. You can call this directly on the Date class.

A useful page for javascript date functions is quackit.com

I mentioned earlier that you should not use getYear();. This is so because this method is not quite Y2K compliant. It is sort of compliant, but browsers don't implement it in the same way. The standard says that it should return the number of years since 1900, which means 2000 would be 100 and 2008 would be 108. Netscape/Firefox does that correctly (possibly because they defined the standard back in the day), but IE decided to 'fix' it by returning 4 digit years for anything past 1999, which means that 1999 is 99 while 2000 is 2000. Your code gets unwieldy trying to manage it, so it's best to just use getFullYear().

I'd always thought about writing an equivalent to strftime for javascript, but never got down to it. In my mind, it would be something that uses a regex with a callback function, and I'd use the unique property of javascript that allows one to call an object's methods like keys in an associative array. Basically something like this:
var fmt = {'Y': 'getFullYear', 'm': 'getMonth', 'd': 'getDate'};
Date.prototype.strftime = function(str)
{
var d = this;
var ret = str.replace(/%([Ymd])/g, function(m0, m1)
{
return d[fmt[m1]]();
});
d=null;
return ret;
};
I'll have to build on that sometime.

Update: I've built an implementation of strftime in javascript. This implementation is also part of the YUI library.

...===...