Your Code Is Too Clever
As programmers we are often to keep things simple, and not to be too clever. While I agree with these principles most of the time, I hope that they are not used as an excuse to avoid finding better solutions for our problems.
How do we define too clever? If we read a code that we can’t understand right away, does it mean it’s too clever?
Let’s take a look at one of the most clever use of case label fall-through in the history of Computer Science: the Duff’s device.
dsend(to, from, count)
char *to, *from;
int count;
{
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
Both clever and confusing, this device leverages C’s relaxed specification of the switch statement to optimize a serial copy using loop unwinding. I can imagine most people being repulsed by the code above – you’re not alone. Even the code’s discoverer said that he felt "a combination of pride and revulsion at this discovery."
But is Duff’s device too clever? I think if you look at it in the original context (which was about real-time animation), it was a brilliant solution to the problem. That is not to say we should start using it in our everday work. Even ignoring issues with how different system architectures and compiler optimizations handle the device, is loop unwinding even useful? Most likely no. There are many ways to get your code to run faster, including new hardware.
How about this piece of code, found in the 3D engine of Quake III to calculate the square root of a float.
float InvSqrt (float x){
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
Notice the magical constant 0x5f3759df. Where did that come from and what does it do? There is a brief explanation given here about this constant. Basically it involves the Newton-Raphson method for approximating square roots.
Is this InvSqrt function unnecessarily clever? I’d say no, because 3D engines have always used mathematical models to draw speed and power from. This function is pretty straight-forward once you understand the math behind it. And in this case, we can’t throw more hardware to increase performance, not unless we want to launch a game that can’t even perform at 50% speed on the best gaming-rig currently available. (I’m reminded of Wirth’s law a little bit)
The point is, we need to pick and choose when to be clever. Principles and guidelines are useful, but they are not meant to be be followed 100% of the time. Aren’t we, as programmers, paid for our ability to think? So think!
Java Is Just Too Slow
Java is slow. And by slow I don’t mean it’s execution speed. I’m talking about development speed.
Java forces you to plan too much. Don’t get me wrong, there’s nothing inherently bad about planning. The problem is that innovation and planning don’t always go hand-in-hand. When you’re making yet another boring spreadsheet application that’s been done a million times before, you can plan out exactly what needs to be done before writing code because you know exactly what you need However, when you’re innovating you need to code as you go. Your ideas may just work, it might need some tweaking, or it may turn out to be horrible. The point is, you won’t know until you start hacking away at the code.
Java is so verbose that in order to really work with it you need to plan ahead. You need to know what Objects you need to create, what methods and variables (private or public?) it should have, and how they need to interact with each other. Oh, and after all that you need to compile your code before seeing the result. As a simple demonstration of this, let’s work with a JSON object in Java (using Gson), then in Python (using simplejson).
Let’s use the following JSON object:
{
'foo': {
'bar': 10,
'baz': 20
},
'phrase': 'Hello World!',
'myArray': [1, 2, 3, 4, 5]
}
Let’s access some data in Java. Wait, first we need to create some Objects to deserialize the JSON string to.
class MyObj1 {
private int bar;
private int baz;
MyObj1() {}
}
class MyObj2 {
private MyObj1 foo;
private String phrase;
private int[] myArray;
MyObj2() {}
}
Now we can deserialize the JSON string and get some properties from it.
String json = "{'foo': {'bar': 10, 'baz': 20}," +
"'phrase': 'Hello World!'," +
"'myArray': [1, 2, 3, 4, 5]}";
MyObj2 json = gson.fromJson(json, MyObj2 .class);
system.out.println(json.foo.bar); //--> 10
system.out.println(json.phrase); //--> Hello World!
system.out.println(json.myArray[1]); //--> 2
Now let’s try the same thing in Python.
import simplejson
json = simplejson.loads('{"foo": {"bar": 10,' +
'"baz": 20}, "phrase": "Hello World!",' +
'"myArray": [1, 2, 3, 4, 5]}')
print(json['foo']['bar']) #--> 10
print(json['phrase']) #-> Hello World!
print(json['myArray'][1]) #--> 2
By the way, the above python code is 100% executable using the interactive shell assuming simplejson is installed (easy_install simple-json). The Java code will need some main method with whatever else, I just didn’t bother – usually my IDE at work writes all the skeleton code for me.
So which do you think is simpler? If you knew you’ll be dealing with a lot of JSON would you go with Python or Java? Another thing to keep in mind is that if I change the JSON string, the Python code would require virtually no effort, whereas the Java code will need class changes, recompiling, etc. Not to mention if I changed the array to something like ["I'm a string", 1234, {"a": 1, "b": 2}, 3, 4, 5]. Sure you can do it in Java, but WHY? You can probably see why Java developers are forced into so many hour-long planning meetings. If you get the wrong the first time you really pay the price.
To be successful on the Web you need a platform that allows you to be innovative. Traditionally, software development involves a long period of planning before any code is written. You go through iterations of UML diagrams before typing a sinlge line of code. This just won’t cut it on the Web.
Traditional software is like cartoon drawing. You usually start with some storyboard sketches of the overall story. This gives the artists a way to previsualize the motion graphic before starting on the real thing. Web applications, on the other hand, is more like a bunch of sketches that are never quite finished. That is, web applications are always evolving, and this evolution happens in smaller steps, and more frequently. You need a language that can allow you to take these smaller steps, and I don’t believe Java is the right tool for this.
JavaScript, Anonymous Function, Closure, and You
There are many things that web developers should know about JavaScript, but the most basic of things are anonymous functions and closure. Both are very powerful tools for anyone working with JavaScript.
So what’s so great about them you ask? Well, I think that’s best explained using some examples.
Let’s say we want to implement a function that will take an integer representing a month, and return it’s name as a string.
e.g. 1 -> ‘January’, 2 –> ‘February’, 9 –> ‘September’
We’ll start out with a naive implementation, but perhaps one that first comes to mind.
function monthName(i) {
var months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
return months[i-1];
}
Simple right? But there’s something wrong with this function. Take a look at the array declaration, it’s inside the function! That means everytime you call the monthsName function, it’ll create an array. This not only slows down your function, but it uses an unnecessary amount of memory.
Our first improvement then, would be to move the array to the outside of the function.
var months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
function monthName(i) {
return months[i-1];
}
Great, now we only create array once! But wait, there’s another problem. We’ve just moved the months array into the global namespace. This is bad because we might be overwriting a previously declared variable also named months. Similarly, someone later on might overwrite our months array. D’oh!
Fortunately, there is a way around this. And this is where anonymous functions and closure come in. Let me show you the solution first.
var monthName = function() {
var months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
return function(i) {
return months[i-1];
};
}();
So how does this work?
First, you’ll notice the block of code inside the outter function is similar to our second solution, except that the function name has been dropped, and it is now the return value of the outter function. The outter function is executed immediately, and is assigned to the variable monthName. Thus monthsName is really the inner function. Sort of.
Here is where closure comes in. The inner function refers to the months array declared outside of it, but because of closure, that array is bound to the function. So when we call the function monthName we are really calling the returned result of an anonymous function (which itself is an anonymous function). And this returned function has the months array bound to it.
Here’s another example using anonymous functions and closure to implement Partial Application in Javascript.
Function.prototype.papply= function() {
var fixed = Array.prototype.slice.call(arguments),
fn = this;
return function() {
return fn.apply(this, fixed.concat(Array.prototype.slice.call(arguments)));
};
}
Of course, you can probably achieve everything I’ve shown here without anonymous functions or closure, but why make it hard for yourself? Learn these tools, use them to your advantage!
Hello Interweb! 1
This is my first attempt at a dedicated programming blog. More interesting posts are on their way, but for now here’s a little info about me!
In my short professional career (which includes several co-op jobs when I attended the University of Waterloo) I’ve mostly been in web development. Actually, I’ve been doing the whole web stuff since about mid-90s, starting with HTML, JavaScript and Perl. Just on my personal/hobby websites.
I’ve worked with many languages, but my current interests are JavaScript and Python. I am a huge fan of Django, and have used it on several projects, including GlobeCampus. I expect the majority of my posts in the near-future to be on JavaScript and Python. ;)
Currently, I’m working as a web developer at The Globe and Mail.