The title of this blog is an oft-repeated mantra, originally said by Bill Gates. It is a large part of the design philosophy behind languages like python and ruby, and it is a significant player in those arguing against languages like Java or C#.
So, is it true?
Well, let’s try an example to show you!
Imagine a hook function (think the comparator function that you supply to a sort function, for example – that’s what we’ll term a hook for this exercise) that needs to return one of 3 different possible values. Something like ‘IGNORE’, ‘ABORT’, ‘RETRY’, to use a familiar little ditty.
How would you make this hook function return its choice?
Our options:
Namespacing
We probably want some sort of ‘RETRY’, ‘IGNORE’, and ‘ABORT’ identifiers that can be used as return value. We can choose to throw these into a namespace directly accessible to the hook function, which would allow the hook function to write ‘return RETRY’ or some such – all done.
Alternatively, we make a new namespace for this, and make THAT accessible, possibly accessible on a global scale, which might even take some sort of ‘import’ or ‘require’ statement. The code in the hook function itself would look something like ‘return ProblemAction.RETRY’.
Structure
Those identifiers have to translate to something. In the old days of C yore, this stuff pretty much always went thusly: You declare (in C, with a more or less global #define) an integer constant named ‘RETRY’.
An alternative is to just make those identifiers link to strings. (ie: string constants). The advantage of that, is that printing the return value or otherwise inspecting it produces a very nicely readable ‘RETRY’ instead of an utterly useless ’2′. The disadvantage is that in extreme situations all those strings might start making a performance impact. These days, that doesn’t tend to become a problem for many projects, so that’s looking interesting as an option.
A third structural option is some sort of compiler-assisted enum construction. Plenty of languages have specific constructs to make enumerated types. Python doesn’t have this, but java1.5 for example does (public enum ProblemType {RETRY, IGNORE, ABORT;} would do it). Those enum thingies tend to keep even more of their structure than the strings (they both print their name AND they have a unique ‘type’). A good compiler or runtime environment should be able to make these even more efficient compared to the string variant in practical use.
Sounds good.
Decision time
So, what option do we take? I had to make this decision today, and I ended up making a full namespaced enum – it would look like ‘return ProblemAction.RETRY’, it would print ‘RETRY’ if you were to print the return value, and its type would be ‘ProblemAction’. You could make a comparison with the usual == as makes sense. So, mostly, this shows how nice java1.5′s enums are, except for this bit:
return ProblemAction.RETRY
is a lot longer than what one would probably see in similar situations for python:
return RETRY
Our, uh, friend, Bill Gates, would seem to prefer the second option because its shorter, and just as readable.
But from a maintainance standpoint, that’s actually the wrong call.
First, a simple thing you’ll have to take on faith: the slightly longer variant isn’t LESS readable just because it consists of a few more characters. The interesting bit is in all caps, the text in front of it makes sense and in some situations might even add some meaning, and the top version is STILL a fairly short one-liner.
So then the main argument for the shorter version is because its easier to type.
But that’s not true. It’s HARDER to type. The reason is this:
In eclipse, I’d type ‘return Pro’, hit ctrl+space, and pick one of the three options from a popup menu. Then I’m done. I only have to ‘remember’ that the return type starts with Pro something*. For this particular example, it seems moot, but imagine there are 20 or so different options. Or it’s a big project and there are about 30 different situations with these things, each with on average 4 options.
So, this means three things:
1) In a good IDE, either option is easy to type. There’s no difference in writing.
2) Given a normal human being, either option is just as easy to read.
3) Given a good IDE, and either a large project or a project you haven’t looked at in a bit, the longer option is easier to remember.
*) In fully static languages + tomorrow’s IDEs, your IDE could reasonably figure out that you must return ProblemActions and just require you to type ‘ret’, and that’s all it takes for the popup menu to be available. Eclipse isn’t there yet, but there’s no reason why it won’t happen eventually. Due to java’s forced declaration (you have to make an interface to contain the structure of the hook function, along with its return type, but on the plus side, the existence of that gives an IDE the knowledge of that structure as well). This is what I think is principally wrong (but fixable) in the very statical and declarative world of languages like java: All that extra information you’re stuffing in your code is not actually being used like it could be.