JavaScript Puzzle - The Too Tidy Assignment |
Written by Ian Elliot | |||
Page 1 of 2 There is a rule about not optimizing code too soon. Perhaps we should add to that the rule that being too tidy is often a mistake. Here we have a JavaScript example where things go wrong because of an attempt to keep the code compact and understandable. Einstein (who would have made a really great programmer if he hadn't wasted all that time trying to figure out the grand unified theory) said "Everything should be made as simple as possible, but not simpler." This is an important maxim for the programmer as well as the physicist. Take, for example, the desire to make code as short and neat as possible. This is sometimes a good idea, but generally only when it improves readability and understanding. It is most certainly not a good idea when the change in syntax brings about an unexpected change in the semantics. In other words Einsteins maxim is easy to say, easy to understand but really hard to put into practice. In this case the problem language is JavaScript and you might say that it is a case of loose syntax providing enough rope to hang the programmer. However, it is likely that similar unintentional constructs lurk in other languages - let use know if you spot any. BackgroundJavaScript is a very simple language and it has few restrictions on how you can put legal bits of syntax together. Sometimes the problem is that things don't mean what you might expect. In other words, JavaScript breaks Ruby's philosophy of not surprising the programmer - that is a language should always mean what you think it means. JavaScript doesn't insist that you declare variables. If you don't then the result is that you will usually end up creating global variables that you never intended creating. As a result most programmers declare variables using the var or let keyword. To combat any side effects from hoisting of declarations to the start of the function or main program, most programmers also move all declarations to the top of the scope. Thus you will often see statements like: function myFunction(){ at the start of a function. To be neat this is usually converted to:
and if the variables need to be initialized, instead of writing:
then:
is much more compact and it works in exactly the same way. Often gathering up declarations and initializations is something that is left for a later stage in code polishing and it usually doesn't cause any problems. PuzzleDuring some code polishing, the following code was discovered:
Most programmer would have thought that this was compact and clear enough, but our enthusiastic programmer was being paid by the character saved and there were eight bytes that could be eliminated:
This works and it is perfectly good JavaScript. Within the function the variables were declared and initialized to zero as can be confirmed by:
The function even passed its unit tests and the whole thing was voted a great improvement, and yet very soon the problems started. Code that once worked with the function stopped working. The question is what is wrong with the change? What semantics have been modified by this seemingly innocent syntactic change? How have we violated Einstein's dictum and made a simplification too far?
|