Your JavaScript Sucks - Rudiments

You have to crawl before you walk. You have to punch before you can Hadoken. – Abraham Lincoln

This post is most likely too simplistic for anyone who has done any kind of JavaScript development for a long time, but it’s always best to start at step 1.

Do NOT Inline JavaScript Calls in Tags

See this?

<a href="#" onclick="DoSomething()" class="monkeys">

Don’t ever do that.

Why? For starters, it violates the separation of concerns. Your markup is your Presentation, JavaScript is not. Your JavaScript will manipulate the markup, but it is not markup itself.

There’s always a workaround for this too. Here’s the equivalent that is unobtrusive using jQuery (you are using jQuery right?):

$('a.monkeys').click(DoSomething);

And you’d put that code with all the other JavaScript in a .js file.

Keep It ALL Separate Anyways

Keep all of your JavaScript in separate .js files. This means not having any <script> tags that do not have src attributes. No sneaking in functions at the bottom of pages, or inlined in views.

Again, why? JavaScript hidden amongst HTML is hard to maintain. If you have a bug in a function, how do you find it? If your JavaScript is spread willy-nilly throughout everything, have fun tracking it down. This code is also hard to test; you’d have to pull in all of your markup into your test suite, which is precisely what you should not be doing for unit testing.

Additionally, you can’t minify inlined JavaScript, meaning you are literally slowing your app down by keeping it all spread out.

The Exception

The biggest exception I can think of for this rule is when you are pre-loading a bunch of data (preferably JSON). If your app is immediately making an AJAX request to retrieve data when the page loads, consider doing this to save the roundtrip:

<script>
    myApp.someCollection = @ViewBag.SomeData
</script>

Watch Out for Globals

By default all JavaScript variables are in the global namespace. This is a Bad Thing. It means that this code right here:

foo = function() {
    // blah blah blah
}

Will clobber any other globally named variable named foo. You can limit this with the var keyword:

var foo = somethingSomething;

But, this is a discipline, because every time you forget the var you create a global object, even if you five layers deep in an object.

Keep Your Functions Small

Open your JavaScript files, what’s the longest function in there? Clocking in somewhere around 100+ lines? Yeah, that’s probably too long.

It’s been said over and over again: smaller routines breed fewer bugs. It seems to endemic to JavaScript to create prolific walls of code, going 10 levels of nesting deep. Break that stuff down into shorter functions, and your life will be a little easier.

Ok, like I said, these are just the basics. Once you start doing them, your code will get a little bit better. Not a whole lot better, but it’s a start. Now that we can walk a little bit (maybe with a limp) we can start to jog later.

Your JavaScript Sucks

JavaScript has been getting a lot of press lately. You can write servers with it, talk to databases, and of course, it’s the most common language in the world. Yet, in its most popular form, client-side scripting on the Internet, it’s just a giant mess.

You know what I’m talking about, that mass of thousands of lines of code that does something-but-oh-God-I-hope-it-doesn’t-break. I’ve written that kind of JavaScript. You have too. It’s a big problem that needs to be addressed.

Why?

First, let’s identify the problems. Here’s a function that I just made up, but it’s not too far from the truth.

Bad_js1
 Fig 1 - A Common Site

How many differentthings are going on here? I can see four right off the bat. Individually, each is not a Bad Thing, but when they’re all within the same function, it’s a problem.

Bad_js4

Fig 2 - Event Binding. We’re looking for something in the DOM, and then attaching an event handler to it.  

Bad_js2

Fig 3 - AJAX. Specifically, communication with our persistance layer.

Bad_js3

Fig 4 - Business Logic. This a simplification, but we’re analyzing the data and making a logical decision based on it.

Bad_js5

Fig 5 - DOM/UI Manipulation. We’re not just reading the DOM here, but changing it.

 

And this little ditty is only 11 lines long. This is the equivalent of inlining your security checks right next to SQL statements, all within a UI template. God help you if you want to actually uncovered a bug in this rat nest down the road.

And let’s not even get into testing. How would you even start writing a unit test for this function? (Hint: it sucks)

Enter MVC

Fortunately, messy code is not a new problem. There is an embarrassment of riches out there to help you get your crap together.

The MVC pattern has been around since the neolithic era of programming. Rails, Django, ASP.NET MVC, CakePHP, etc. have been making developers’ lives much easier on the server side for years. And now, some of that has trickled down to JavaScript.

Centipedes

A common reaction.

What makes MVC so popular amongst developers is that it forces you to break your code down into manageable chunks. Mixing AJAX calls and DOM Manipulation in the same functions just doesn’t fly there.

And, you have a bunch to choose from. In future posts, I’ll be giving a brief description of some of the popular ones. Spoiler: I myself have been using Backbone and will be going into deeper detail on that one.

My Reaction to the Rumor that Nikon is Looking to Buy WebOS

In the span of about 30 seconds.

"What? WHY?"

Thinks for a minute about a sweet WebOS powered camera.

"Well, it could work"

Thinks about every other piece of software Nikon has made.

"They'll screw it up."

My New Email Signature

Spurred on by some of the more recent mails I've received. 

Screen_shot_2011-09-13_at_11

I did blur my phone number and address because there are bad people out there. Rest assured that the address used comic sans.

How I Setup a PhotoBooth

First, a Demo Video1

(download)

I was slated to take some pictures for my church’s high school group’s kick off for the new school year. They gave me the opportunity to either walk around and take “action” shots and candids, or to set up a “booth” and do more posed portraits (with goofy props and such). The booth is typically just a backdrop and a flash or two for lighting.

I wasn’t terribly keen on the booth idea: it get’s a little boring after a while. But, the kids typically love that kind of stuff, so I didn’t want to just abandon it. Sure I could have switched hats and jumped back and forth between the two, but after thinking for a bit, I realized that I could do both using the magic of computers!

My idea was pretty basic: just set up a camera on a tripod and have some sort of remote trigger that the kids could just hit. The trick is to make it easy enough for anyone to use. Here’s the equipment I went with:

  • A camera that supports tethered shooting. I used my Nikon D300.
  • A tripod to put the camera on. I have a Manfrotto something or another.
  • Lighting & Backdrop. I just used a single flash and a 45” shoot through umbrella. Backdrop was just a 9’ wide white seemless.
  • Computer. Had a 24” iMac available.
  • “Trigger” I ended up using an Apple Magic Trackpad.
  • Software. I’ll get into this in a bit.

I used the iMac because it could handle all the triggering stuff, and also display the results so that the subjects could immediately see themselves.

The user interaction needed to be as simple as possible: The subject pushes the trackpad button. The computer counts down 5 seconds, takes the picture, displays it for a few seconds, then goes back to the countdown screen for the next shot.

For the trigger, my original thought was to get something like the Staples “Easy” button. The only similar things I saw online were buttons that could only open a browser and go to a specific URL. And you had to buy a hundred at a time… So that wasn’t going to work. I’m not much of a hardware guy so the thought of hacking something didn’t appeal to me.

After some pondering, I realized that the Magic Trackpad was really just one big button. The trick was going to be how to get a click from that to trigger the camera. I first looked into using Adobe Lightroom. It supports tethered shooting right out of the box, and it works pretty well (I use it for 99% of my photo management and editing). The problem is that I don’t want to expose the whole of Lightroom to a kid who just wants to take their picture. Putting a sign up that said “Move the mouse to the gray circular button next to the esoteric camera settings and click it. And please don’t mess with anything else.” wasn’t really an option.

Fortunately Mac OS X has all kinds of scripting support. If you know what you’re doing, you can simulate just about anything. There’s something called AppleScript built in to the system that is designed for something just like this2. I figured I could use AppleScript to trigger the tether button in Lightroom to take a picture.

This is when I hit my first big snag. I can’t say for certain, but it looks like the shutter release button isn’t actually a button, or at least it’s not recognized by OS X as a button element. This means that you can’t tell AppleScript to click it. There are ways to ask an app to tell you all of its textfields, labels, buttons, etc, and LightRoom wasn’t giving up the goods for that particular one. My best guess is that the programmers at Adobe couldn’t get the traditional OS X button to look the way they wanted it to, so they drew it their own way, captured the mouse click and then triggered the shutter release based on the mouse coordinates. Long story short, that button is simply not accessible via scripting.

After some googling around, I found a nifty little app called StudioTether. It is a tiny app whose UI is just a single button that triggers the shutter release on the camera. And it was accessible via AppleScript. Here’s the script I ended up going with.

The trick is to get that script to fire every time the Trackpad was clicked. Now, I am a software developer by trade, so this sounded more up my alley. I thought that if an app could stretch to the full screen of the monitor, then no matter where a person clicked, I could capture that event and then call the AppleScript, which would then trigger the camera.

Still with me? Good because then it got complicated. I had never actually written software specifically for the Mac, so this was a first for me. I could dedicate several blog posts about my experiences learning Xcode, Objective C, and the Cocoa framework. I was able to stumble through though, taking somewhere between 20-30 hours, and the result is pretty slick.

The camera settings weren’t too exotic. I used an aperture of f/5.6. In my normal portraiture I prefer wider, but the margin of error in terms of where the subjects could stand was bigger, I stopped it down a bit. However, this also meant that there was less light coming into the camera. I didn’t want to blast my flash at full power each time, since that would chew up the battery and drastically length the recharge time, so I bumped the camera’s ISO up to 800. This enabled the flash to be at 1/4 power. ISO 800 isn’t ideal, but doesn’t impact image quality too much on a D300.

I normally shoot photos in RAW mode as well, but decided to use JPG here, at medium quality. The purpose of the whole thing is to just be plain fun for students; nobody was going to be wanting 20x30” blow-ups of these. This also had the benefit of keeping the filesize down, meaning that the images were transferred to the computer and displayed faster.

Nothing is perfect, of course. Because the nature of the TrackPad is to manipulate the cursor, it would sometimes register the user action as a drag, rather than click, and not do anything. If someone just mashed their hand (or fist, sigh) on it, that would sometimes not register as well. The perfect solution to that problem is to get a big “Easy” type button, but as mentioned, I can’t seem to find one that’ll work.

Aside from those small things, it was a rousing success. Over 400 pictures were taken in just a couple of hours. Every time I walked by, people were having a fun time and taking multiple pictures.

(download)

  1. Video done by my friend, Jay Worsley. If you need a video made, look him up.
  2. AppleScript is generally a poorly written programming language, but it does work pretty well for scripting UI elements.

 

Haven't Heard Back Yet

I just couldn't help myself.

Job_offer

Nice Feature in Lion

Actually, this may have preceded Lion, but I rarely use Safari so I don't know.

My Internet connection died (thanks Cox!). Opened a page in Safari and got the "Safari can't connect to the Internet" screen. Rebooted router. When connection was re-established, the page I was trying to reach was automatically reloaded and popped up while I was going through my Instapaper queue. Nice job, whoever implemented that.

I Think the Cable Companies are Screwed

I just ordered two Roku boxes for our house. We have a Netflix Instant subscription, and will likely be converting our Hulu Plus trial into a full subscription as well. Once they arrive we will likely be killing our cable TV service. And if there's a random show that doesn't pop up on either of those, iTunes can fill it in. We are currently paying somewhere in the neighborhood of $50 per month for cable, and both of those subscriptions run $8 each, so we should be saving a decent chunk of money each month.

The only things I will be missing will be live sporting events, which I watch less and less, and can always go to a bar or wherever.

I have no idea how long this will last, and I do wonder if both Netflix and Hulu can continue to offer such a low rate for their services.

Spotify & Rdio

And now, here's my arbitrary and subjective look at Spotify and Rdio.

Spotify has now launched in the US. This is good news. I had originally checked it out a year ago using a proxy to pretend to be British1, but it was too much of a hassle to keep maintaining the proxy connection to be worthwhile. Fortunately around the same time I discovered Rdio, and have been a happy subscriber with them ever since.

But now, there's a choice! Since I had that other account, I was able to just switch my location and jump right back into Spotify. So, let's do a little compare and contrast between the two services. I have the Rdio Unlimited plan ($10/month) and since I'm just sampling Spotify, using their limited free plan.

Ads
Rdio offers no free plan, but with Spotify you can get 10 hours of music per month with ads, both as banners in the app and audible ones between songs. The ads are pretty obnoxious, but that's what you get for free. Some people are actually complaining about this. I just want to make sure that I'm understanding this one: You want a music service that gives you unlimited access to music, for free, with no advertisements at all, right? Why not ask for a pony that craps skittle flavored gold too?

If I do switch it'll be to a paid Spotify plan, so ads are a moot point with me.

Music Selection
Both seem to be pretty comparable. There are some gaps (both their Calexico selections are far too weak), but my tastes are well represented.

Rdio is better at finding new music. They have a Recommended page that suggests music that you might like based on your listening habits, but I've never had much luck with it. What I do find useful is Rdio's New Releases section. It lists all the albums that are new to Rdio (new releases, re-issues, or just new to the service).
Screen_shot_2011-07-14_at_10
Most of the stuff I just don't care for, but there's usually a couple of things worth listening to each week.
Spotify does have a "What's New" page, but it isn't nearly as good. It lists only 8 albums at a time, and those don't seem to have a clearly defined meaning of "new": there's a Brittney Spears album there that's been out for a while (I think), I don't know if it's new to Spotify, or just "Hot". 

Rdio also has a radio utility, which will play random songs based on what is on your current screen, and other criteria you can provide. It's no Pandora, but works as a decent Party Shuffle if that's what you're looking for.

Library Management
Spotify's playlist implementation is much better than Rdio's, period. Unless I'm missing something, you can only add or remove songs one at a time with Rdio. This is downright painful.
Screen_shot_2011-07-14_at_10
Spotify presents lists as a standard list view, meaning you can select multiple things, and then do whatever you want with them.
Screen-shot-2011-07-14-at-10

Neither of them support complex or "Smart" playlists like can be found in iTunes. This is really too bad, since it's a powerful feature2.

Additionally, Spotify has a "favorites" functionality. You can click the star icon next to a song, which will add it to the special Starred list. Rdio doesn't have anything like this. I ended up creating a playlist in Rdio called "Neato" and manually added songs to that, which isn't nearly as nice.

Both apps will look at your local music and add it to the library if you'd like that (I don't), although Spotify keeps things a little cleaner by having a separate Local Files list in their sidebar.

Spotify's concept of a Library is: "Music you've starred, imported, bought, or added to a playlist". This is a problem for me. If I like an album, I want to add it to my library. The only way to do this is to add it to a playlist or star it. I ended up creating an Everything playlist and dropping stuff in there, which doesn't feel quite right. Rdio's library (called Collection) is just a big bucket. You can click on a song or album and add it to your Collection. This makes more sense to me, and seems more analogous to a traditional CD collection.

Rdio will kind of give you metrics on what you have listened to. In your collection, there are blobs of artists (or songs). The bigger the blob, the more you've listened to that artist (or song). Hovering over a blob will give you an exact number, but that's about it. I'd prefer something like iTunes's actual playcount on each song.
Screen_shot_2011-07-14_at_10
It also is not all that representative; I saw that The Clash's Sandinista! was available, but that's a big triple album; each run through counts as 36 listens. It's a good album, but I've only listened to it 3 times in the last year and it is rather prominent on my Most Played list.

UX
You can do more with Spotify, but I found Rdio's interface to be more intuitive. Both apps support creating a queue of songs to serve as a running playlist. Spotify's has some weird behavior associated with it. If you are on track 3 of an album, and then add another to the queue, that new album will start as soon as the current song has ended. I would expect it to queue up at the end of the list, as Rdio's does.
Screen_shot_2011-07-14_at_10
And I have no idea what's going on here. I added the Bon Iver album, and two others after it, but it is still showing up at the bottom of the queue, with no way to remove it. I don't know what will happen once I reach the end of The National album that's queued up.

Update - this has taken a while to write, so my queue finally worked its way down to those repeated Bon Iver tracks, and played them again... Still don't know how that happened.

Social
Both services have standard Twitter and Facebook integration. Nothing special here. 

One thing that Rdio does have over Spotify is that it supports embedding a little widget in a web page that will play a clip of a song. This is pretty handy to share stuff with non-Rdio subscribers. The only wish I have was that it would play the whole song, like the late lamented Lala, but I doubt they'd ever be able to wrangle the content providers into allowing that. Spotify has something similar, but requires listeners to have Spotify accounts to listen in, and isn't embeddable.
Widgets
Rdio also has its own social network built into it. You can follow people and see what they listen to. Of course, this is only as useful as the number of people you know with similar tastes as yourself.

Both services have desktop apps for Mac OS X. Both support the media keys for play/pause, next, and previous. Rdio uses Flash for it's rights management streaming, but nowadays bundles it with the app (like Chrome). I don't have Flash installed system wide, so this is a nice touch. It doesn't look like Spotify is based on Flash tech, or at least, I couldn't find any in the Package Contents.

Conclusion
I really like Spotify's playlist management, but I think I like everything else in Rdio more. I can live with (and have for the past year) Rdio's crummy playlist support, but I don't know if I'd be alright with Spotify's UI quirks. I think I'll hang on to the free version of Spotify to see if they can iron out some of the UI issues, but I'm not going to be canceling Rdio any time soon.

Notes
1. I found the ads for "Crisps" delivered in "proper English" to be downright delightful.

2. For example. I have a playlist in iTunes called "Pool" that has songs that are: at least 3 stars, longer than 30 seconds (to avoid terrible "skits"), and not holiday music. Then, I have another playlist called "Good" that takes only songs in Pool that are 4 or 5 stars, and haven't been listened to in the last month. This is my main list to listen to: it rotates my favorite songs and doesn't get stuck on the same songs over and over. Nothing like this is possible to Rdio or Spotify.

Kind of Screwed - Devil's Advocate Edition

Andy Baio's 8-bit version of Miles Davis's seminal album is pretty interesting. Not really my style, but it's very well done. Unfortunately, he has hit a really big legal snag. Jay Maisel, the photographer who took the cover shot of the original album, sued Baio over the altered cover he used. In order to avoid a drawn out and expensive legal battle, Baio settled for $32,500. The Internet has collectively flipped out. 

Here's what I wrote on the Hacker News story about it:

What would the reaction be if, for the sake of argument, EMI took a photo that a small independent photographer made, ran it through what looks like a basic Photoshop filter, and slapped it on the next Coldplay album? Internet outrage right? 
 
And then what would happen if the photographer sued EMI and Coldplay, and won a $32K settlement? I'm guessing the Internet would either be satisfied or angry that $32K is too little for such deep pockets.  
 
I understand and agree that Jay was too vicious in this, but how is he in the wrong again?

About

These are my mostly unfiltered thoughts.

Twitter