Trust no Strings
Been delaying to write this post for a long time, I think it’s something that experienced developers or people coming from strong typed languages like Java or C# probably already know what I’m going to talk about but for JavaScript developers I think it will be an important information since everyday I see someone (or some famous open-source project) doing it “wrong”.
Strings are evil
Strings are error-prone, a small typo error and your application won’t work as expected and the compiler/environment/VM/etc probably won’t give you any error messages, consider the code below:
calendar.showMonth('feburary');
calendar.dispatchEvent('monht/show');
Did you noticed something wrong? “February” and “month” were misspelled, depending on how the code is written you won’t see any error message and have no idea why the month isn’t being displayed and why the event listener isn’t being called…
Constants
Because of this kind of error that a lot of people started creating pseudo-constants to store string values, numbers, etc…
var FEBRUARY = 'february',
ON_SHOW_MONTH = 'month/show';
...
calendar.showMonth(FEBURARY); //error since var FEBURARY is not defined.
calendar.dispatchEvent(ON_SHOW_MONTH);
By using a pseudo-constant (JavaScript doesn’t have real constants) the code above will throw an error telling that FEBURARY doesn’t exist. You don’t need to spend 1 hour trying to find out what went wrong, it takes less than 1 minute to spot the error, if you are running JSLint/JSHint during each file save (highly recommended approach) it would display the error without even needing to run the code (extra bonus).
“Errors should never pass silently. Unless explicitly silenced.” – The Zen of Python
Another advantage is that code completion will probably work better so you won’t mistype the constant name and don’t even need to type the whole word/sentence since it will auto complete it for you.
Readability
On many languages (PHP/Java/C#/etc..) a lot of settings are stored as integers, they create constants for each one so a value that may be unreadable like showError(5045) becomes readable showError(WRONG_INPUT).
“It’s harder to read code than to write it. This is why code reuse is so hard.” – Joel Spolsky
Maintainability (added 2011/11/05)
If for some reason you need to update the value you just need to change it on a single place, it will avoid code duplication and errors introduced by updates. You also concentrate all the important info and settings, making it easier to update. Having strings spread over your whole code base is usually a sign of code that is hard to maintain (specially if same value appears in multiple places).
Beware! (added 2011/11/05)
var MONTHS = {FEBRUARY : 'february'},
EVENTS = {SHOW_MONTH : 'month/show'};
...
calendar.showMonth(MONTHS.FEBURARY); // `undefined` (no error thrown)
calendar.dispatchEvent(EVENTS.SHOW_MONTH);
As spotted by Arieh in the comments, accessing non-existent properties of an object returns undefined without throwing any errors. Make sure you validate the passed values to check if they do exist and are valid (trust no strings).
Constants are better but not the definitive solution
Constants solve the problem but they are also verbose and can be tiresome to create it for every single value… Another option is to create specific functions and properties for each existing option, e.g.:
//can be just an alias to a "private" method `_showMonth(name)`
//it can even be automatically generated (since JS is a dynamic language)
calendar.showFebruary();
//created an object "on" to store all the event types
calendar.on.showMonth.dispatch();
Another option is to use integers when it does make sense (not as safe but harder to mistype and usually easier to validate):
calendar.showMonthByIndex(1);
PS: “indexes” always starts at zero (like array indexes), if the value should start at 1 use the word “number” showMonthByNumber(2).
More
So remember, every time you pass strings to functions or write code that relies on strings consider if using a constant or creating a new method wouldn’t be a safer approach (specially if it is a public method) or make sure you provide error messages if the user passes the wrong values. Code compressors like Google Closure Compiler and UglifyJS will usually inline the constants or shorten their names so file size isn’t an issue in most cases.
This kind of silly error was one of the main reasons why I decided to code JS-Signals. After I started using Signals the amount of stupid errors related with typing decreased a lot, I already knew that strings were evil for a long time and been using constants for all my AS3 events but in JS sometimes I was just taking the “shortcut” and using strings for things that should be constants…
Code in a way that will reduce the chance of errors and that will make code more readable, if you feel you are typing too much you are probably using the wrong editor or not coding on a way that helps your work flow… - I enabled word completion on Vim to all the words on any opened file so typing showMonth and showMonthByIndex takes about the same time if it is already defined…
This presentation by Douglas Crockford is really good and point some common errors that made him create JSHint.
“There will be bugs. Do what you can to move the odds to your favor.” – Douglas Crockford
Good coding and always remember: Strings are evil.
Related
- Naming methods, properties and objects
- Comparison between different Observer Pattern implementations
Edit: Fix constant examples, add info about accessing undefined object properties and maintainability.