Don’t get the Dalek! – Tips for debugging JavaScript.

, , , , , , , , , ,

(For those of you who aren’t in the know, the Dalek is an evil alien species from the Seminal BBC show ‘Doctor Who’, they’re bent on galactic domination but are thwarted by the heroic Doctor every time.)

You got the Dalek!

The Dalek and the Tardis crosstek uses

In some places it’s been ‘The Sombrero’, ‘The Snickers Bar’, ‘Buying the Donuts’, or ‘Setting off the siren’. Here at Crosstek it’s known as ‘Earning the Dalek’. In our team whenever someone commits an error that breaks the build or does something especially “bad” they’re given the Dalek to hang on their desk until someone else earns it. It’s a tradition that helps the team keep a shorthand version of accountability, and at the same time reward people for doing exceptionally good work (via the tardis). It’s an unofficial form of checks and balances that can give you a barometer of how well your coding practices are going.

Most of the time, a lot of errors are caused by careless programming mistakes. In order to help you not ‘Earn the Dalek’, take a look at some of the most common issues.

1. Misplaced semi-colon or comma.

//Missing a comma, colon, and semicolon here. Can you find them?
var outcomes = [
[{action:"tie", word:"is unaffected by"},{action:"lose", word:"is covered by"},{action:"win", word:"smashes"},{action:"win", word:"crushes"},{action:"lose", word:"is vaporized by"}],
[{action:"win", word:"covers"},{action:"tie", word:"is unaffected by"},{action:"lose", word:"is cut by"},{action:"lose", word:"is eaten by"},{action:"win", word:"disproves"}],
[{action:"lose", word:"are crushed by"},{action:"win", word:"cut"},{action:"tie" word:"are unaffected by"},{action:"win", word:"decapitate"},{action:"lose", word:"are melted by"}],
[{action:"lose", word:"is crushed by"},{action:"win", word:"eats"},{action:"lose", word:"is decapitated by"},{action:"tie", word:"is unaffected by"},{action:"win", word:"poisons"}],
[{action:"win", word:"vaporizes"},{action:"lose", word:"is disproved by"},{action:"win", word:"melts"},{action"lose", word:"is poisoned by"},{action:"tie", word:"is unaffected by"}]
]

These are a pain because you can almost never tell where they are in a JavaScript file. (Much of the Development at crosstek is in JavaScript via node.js. It’s awesome.)

  • Make sure to run your code early and often to see when your commas or semicolons go missing.
  • Use a standard way of placing commas in functions. By standardizing which place you put them, you’ll always know which side of the line of code to look for them.
  • Use a tool to validate your JavaScript when available. Some development environments come with these built in.

2. Misspelled Variable names

//One of these variables or methods just got misspelled. Can you pick out which one?
function compare(choice1, choice2) {
	var outcome = outcomes[getIndexOfChoise(choice1)][getIndexOfChoice(choice2)];

	return " You " + outcome.action + "! " + choise1 + " " + outcome.word + " " + choice2;
}

While it’s great to use long, descriptive, variable names, try to make it something that’s easy to spell for you. Naming something useTheForce is pretty easy compared to something like neededDeerReader or something of the such.

  • Use auto suggestion of variable names when you can. This won’t work for everyone all the time though
  • Try to use camel casing or some other variable naming method that makes it easier to read. usetheforce < useTheForce = use_the_force > If all else fails, just copy and paste the variable name from where you declared it.

3. Argument Mismatch

//Forgetting one argument here makes the whole thing not work correctly
function takeFive(employeeNames, thingTheyDo, callBackFunction){
	console.log("Alright, " + employeeNames + ", take a break from " + thingTheyDo + ". Take five!");
	callBackFunction();
}

function coffeeBreak(breakLength, coffeeType){
	for(var i = 0; i < breakLength; i++){
		console.log("Drank a " + coffeeType + " Coffee");
	}
}

function takeABreak(){
	var employees = "Chris, John";
	var programming = "programming";
	var breakLength = 10;
	var coffeeType = "black";

	takeFive(employees, function(){coffeeBreak(breakLength, coffeeType)});
}

This personally how I earned my last Dalek from the team. I had a function called as a callback to another function, and I put the arguments on the wrong callback. This is where tabbing is important.

  • Use the collapsing and expanding functions feature built into your IDE to regularly check your functions.
  • Have your sub-functions throw errors if they’re not give the proper parameters. Strict type checking also helps a ton too.
  • Always order your variables you’re passing from most important to least important when creating a new function.

4. Scope issues

//Pay attention to the difference between _this and this!
var weaponOfChoice = {
	name:"fatboy slim"
	,song:"weapon of choice"
	,verseFirst: "You can go with _this, "
	,verseSecond: "Or you can go with that."
	,sing:function(){
		var _this = this;
		var firstThree = function() {
			for(var i = 0; i < 3; i ++){
				console.log(_this.verseFirst);
				console.log(this.verseSecond);
			}
		}

		console.log(this.name + " : " + this.song);
		firstThree();
		console.log("Or you can throw with us!");
	}
}

Javascript is really funky about scope and doesn’t behave like a true Object oriented language at all. As the saying goes, Javascript is to Java as Carpet is to Car. ‘this’ refers to the object which has called the method and is now the scope of reference. Basically, whatever calls something is now referred to as ‘this’. (‘this’ and scope in javascript is a little confusing. Take a look at this post)

  • Use lots of console.log(this); to figure out what the scope is if something isn’t being called correctly.
  • Watch out with variable naming when storing a scope using var _this = this; Code hinting can help or hurt you here depending on what you’re wanting.

5. Dependency issues

Libraries, you need to use them, right? Specifically, you need to use them in the right order to make them work well for you. If you don’t you can run into a slew of problems.

  • Whenever you re-factor your code, make sure all your libraries are loading correctly and via the correct methods (HTTPS vs HTTP issues are troublesome).
  • Consider using something to manage your libraries, such as require.js

Until next time. X’s Up!