Last Updated: February 25, 2016
· geetotes

The Case of the Bad MapReduce

I dabbed the sweat from my brow with the stack of deli napkins left over from eating in front of my terminal. The power company had cut the electricity two weeks ago due to non-payment, leaving me with no A/C right in the middle of a heat wave. Things were slow for a code detective like myself; I had even taken to crawling the local newspaper ads for *shudder* wordpress cases.

Then, a knock on my door. I peered through the frosted glass trying to see if it was a client or a bill collector. But she opened the door too fast for me to come to a conclusion.

In walked the most gorgeous dame I've ever laid my eyes on. This was no bill collector; I could tell from her well-toned fingers and soft hand she had spend a lifetime on the home row. Her bright, curious eyes examined me from behind her thick glasses; the glasses being no doubt a result of many weekends digging through the internals of FreeBSD.

"How can I help you?" I asked while sizing her up for how much I could charge. While my reptilian brain went to thoughts of a relationship -- flirty texts accidentally ended with :wq due to vim-ified muscle memory, heated debates about the differences between Federation replicator and transporter technology -- my business brain started sizing her up for how much I could charge. Hot or not, I still had no A/C.

"I'm having trouble with Backbone.fetch(). I come from kernel programming-land, so I'm not too familiar with this web stuff, which I why I came to you." she said.

I had dealt with Backbone.fetch() before. An often misunderstood and abused method, my case file on Backbone.fetch() was a couple of inches thick.

"Can you tell me more?" I asked. Trying to pull off a cool, nonchalant attitude, I leaned back in my office chair.

"Well, Backbone.fetch() isn't always triggering the 'reset' event. I'm fetching a collection"

Damn, this would be a simple case. My dreams of high billings floated away. I suggested we attache some debugging to the instance of the collection:

  success: (xhr, textStatus) ->
  error: (m, r) ->

"Wow, this is helpful! Thanks Detective GeeTotes!" she said, flashing a winning smile.

She hit refresh on the browser, and the responseText was a bunch of JSON.

"That's weird" I said, giving the JSON a quick look. "It looks well formed to me. But let's double check".

When I copied and pasted the JSON from Chrome's debugger into, I couldn't help but notice she wasn't running a traditional window manager. She was a xmonad babe.

JsonLint returned an error... there was a NaN in the JSON. I pointed to the screen.

"Well, there's you're problem. Invalid Json, so success never fires, and nor does reset".

"NaN? But I'm checking for that in my MapReduce -- I'm using MapReduce to generate the JSON for Backbone."

I asked to see the MapReduce. Now that MapReduce was involved, this could prove to be a particularly finicky bug. MapReduce is always a pain to debug, especially when you're dealing with thousands of records.

She opened the map reduce and showed me a snippet.

var averageScore = Math.ceil(score / totalScore);

"Ahh" I said, pointing to the screen. "There's you're problem. $20 bucks says somewhere during the MapReduce there's a division by 0".

She smacked her forehead. "Of course! How would I check for NaN?"

I told her about the uniqueness of NaN in javascript, and how it doesn't evaluate to true or false in control statements. Then I showed her the isNaN() built-in javascript method.

var averageScore = Math.ceil(score / totalScore);
   averageScore = 0;

After that, the MapReduce worked perfectly.

"Detective GeeTotes, you're amazing!"

"Thanks." I grinned sheepishly, not wanting to spoil this moment by talking about my bill. Then, thinking back to her window manager:

"So, um, you like Haskell?"