:::: MENU ::::

Friday, December 12, 2008

I’ve noticed that the developer and designer community appear to be obsessed with lists. Is this for a reason that I have somehow missed? For example, over at dZone, 2 out of the top 3 most popular articles are lists: 15 CSS Tricks That Must be Learned and 10 Dirty Little Web Development Tricks - incidentally I liked both articles so I seem to have this obsession myself. OK this is not that many but hey I’ve seen loads of lists elsewhere. Anyway, I thought I would embrace this culture to feed my own addiction and I have detailed 7 (I was only going to do 5, and 6 was out as it’s not prime ;-)) ways to write beautiful code.

First things first here, I’m talking about pure aesthetics, nothing else. As I have said previously, good code starts by being something other people find easy to read. In fact, Jeff Attwood had a blog post comparing coding to writing citing several sources. I urge you to take a look.

Anyway on to my list.

  1. Return from if statements as quickly as possible.

For example, consider the following JavaScript function, this just looks horrific:

1
2
3
4
5
6
7
8
9
10
11
12
13
function findShape(flags, point, attribute, list) {
    if(!findShapePoints(flags, point, attribute)) {
        if(!doFindShapePoints(flags, point, attribute)) {
            if(!findInShape(flags, point, attribute)) {
                if(!findFromGuide(flags,point) {
                    if(list.count() > 0 && flags == 1) {
                          doSomething();
                    }
                }
            }
       }
    }   
 }

Instead we can change the above to the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function findShape(flags, point, attribute, list) {
    if(findShapePoints(flags, point, attribute)) {
        return;
    }
 
    if(doFindShapePoints(flags, point, attribute)) {
        return;
    }
 
    if(findInShape(flags, point, attribute)) { 
        return;
    }
 
    if(findFromGuide(flags,point) {
        return;
    }
 
    if (!(list.count() > 0 && flags == 1)) {
        return;
    }
 
    doSomething();
 
}

You probably wouldn’t even want a function like the second one, too much going on (see point 7), but it illustrates exiting as soon as you can from an if statement. The same can be said about avoiding unnecessary else statements.

  1. Don’t use an if statement when all you simply want to do is return the boolean from the condition of the if.

Once again an example will better illustrate:

1
2
3
4
5
6
7
8
function isStringEmpty(str){
    if(str === "") { 
        return true;
    }
    else {
        return false;
    }
}

Just remove the if statement completely:

1
2
3
function isStringEmpty(str){
    return (str === "");
}
  1. Please use whitespace it’s free!

You wouldn’t believe the amount of people that just don’t use whitespace - you would think there was a tax associated with using it. Again another example and I hesitate to say this but this is from real live code (as was the first example), all I have done is change the programming language and some function names - to protect the guilty:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getSomeAngle() {
    // Some code here then
    radAngle1 = Math.atan(slope(center, point1));
    radAngle2 = Math.atan(slope(center, point2));
    firstAngle = getStartAngle(radAngle1, point1, center);
    secondAngle = getStartAngle(radAngle2, point2, center);
    radAngle1 = degreesToRadians(firstAngle);
    radAngle2 = degreesToRadians(secondAngle);
    baseRadius = distance(point, center);
    radius = baseRadius + (lines * y);
    p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
    p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
    pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
    pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
    // Now some more code
}

I mean I won’t bother putting an example of how it should be - it should just be sooo bloody obvious. That said, I see code like this ALL the time and so certain people do not find it that easy to judge how to use whitespace. Screw it, for them I will inject some whitespace into the example and it’s shown below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function getSomeAngle() {
    // Some code here then
    radAngle1 = Math.atan(slope(center, point1));
    radAngle2 = Math.atan(slope(center, point2));
 
    firstAngle = getStartAngle(radAngle1, point1, center);
    secondAngle = getStartAngle(radAngle2, point2, center);
 
    radAngle1 = degreesToRadians(firstAngle);
    radAngle2 = degreesToRadians(secondAngle);
 
    baseRadius = distance(point, center);
    radius = baseRadius + (lines * y);
 
    p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
    p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
 
    pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
    pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
    // Now some more code
}
  1. Don’t have useless comments:

This one can get quite irritating. Don’t point out the obvious in comments. In the example below everyone can see that we’re getting the students id, there is no need to point it out.

1
2
3
4
5
6
7
8
9
10
11
12
13
function existsStudent(id, list) {
    for(i = 0; i < list.length; i++) {
       student = list[i];
 
       // Get the student's id
       thisId = student.getId();
 
       if(thisId === id) {
           return true;
       }
    }
    return false;   
}
  1. Don’t leave code that has been commented out in the source file, delete it.

If you are using version control, which hopefully you are - if not why not! - then you can always get that code back easily by reverting to a previous version. There is nothing more off putting when looking through code and seeing a large commented out block of code. Something like below or even a large comment block within a function itself.

1
2
3
4
5
6
//function thisReallyHandyFunction() {
//      someMagic();
//      someMoreMagic();
//      magicNumber = evenMoreMagic();
//      return magicNumber;
//}
  1. Don’t have overly long lines.

There is nothing worse than when you look at code that has lines that go on forever - especially with sample code on the internet. The number of times I see this and go ahhhhhhhhhh (I’ll switch to Java for this, as generics makes this particularly easy to do):

1
2
3
4
5
6
public static EnumMap<Category, IntPair> getGroupCategoryDistribution(EnumMap<Category, Integer> sizes, int groups) {
        EnumMap<Category, IntPair> categoryGroupCounts = new EnumMap<Category,IntPair>(Category.class);
 
        for(Category cat : Category.values()) {
            categoryGroupCounts.put(cat, getCategoryDistribution(sizes.get(cat), groups));
        }

I’m not suggesting the 70 characters width that you had to stick to on old Unix terminals but a sensible limit like say 120 characters makes things a little easier. Obviously if you are putting sample code on the internet and you have it within a fixed width container, make it easier for people to read by actually having it fit in the container.

  1. Don’t have too many lines within a function/method.

Believe it or not a few years ago now an old work colleague exclaimed that Visual C++ was “shit” as it didn’t allow you to have a method with more than 10,000 lines. I kid you not - well ok I can’t remember the exact number of lines but it was huge. I still see this time and time again where a function/method is at least 50 lines long. Can anyone tell me this is easy to follow? Not only that but it normally forms part of an if statement that you can never find the enclosing block because you are scrolling. To me anything over 30-35 lines is pretty hard to follow and requires scrolling. My recommendation is if it’s more than 10-15 lines consider splitting it up.

This is by no means an exhaustive list and I could have gone on longer - in fact my abolish the switch statement motto would have been number 8 if I had not already mentioned it before. However, it has to end somewhere but feel free to state your own annoyances and maybe I can update the post with some more.