13
Aug 11

Developer litmus test

Here’s the situation: you need to hire a new developer. You’ve put up a job posting, you’ve got ton of CVs, and even after you discard the ones obviously not suited to the job, you still have a lot more potential candidates than you’d like to interview in person.

One way to trim this even further is to give them a task and see how well they execute it. Unfortunately, this only tests the programming abilities of the candidate. While important, these are not the only skills they need to have. Also, the assignment can easily be gamed – the candidate can ask (or even pay) someone to solve it for them.

The “patches welcome” test

Open source contributors usually start by making a small tweak or fix in the existing project code, not by developing all new codebase. Similarly, new hires usually first work on the existing code, before being put in charge of a new component of the system.

Can we apply the same principle to candidate assignments? I think we can.

We can make up a standalone project that uses the same languages or framework that the new hire will use – something that can be done in a day. We actually implement it, but leave it full of errors (syntax, logic, or valid but obviously poorly performant code).

The setup

Instead of writing corret code and inventing errors, it’s better to just write the whole thing in one go, never bothering to check and fix any syntax or logic errors (in fact, it’s best if you disable syntax highlighting and other code validation checks that your editor might have).

We put the project on a code hosting site and give the candidates no further instructions than “this needs fixing, documenting and unit tests – patches welcome.” We leave the code wide open, so candidates don’t think we’re abusing the test to have the “real” work done.

Then, we wait, see what they come up with.

Benefits

This tests a lot:

  1. whether the candidate can use git (or hg or your preferred vcs) or, failing that, that they can (and do) learn the very basics
  2. whether they can read and understand others’ code and modify/refactor it without making it into a pasta
  3. that the candidate can actually program and fix the code in question
  4. that they know the frameworks or libraries you need them to know
  5. whether they can follow the code/style conventions
  6. that they write unit tests (if applicable to the assignment)
  7. whether they’ve identified valid but poorly performant parts of the code
  8. can they write documentation
  9. whether they split their work in smaller chunks (commits/patches) or give one big code dump at the end

Conveniently, it also serves as a quick intro for your coding practices for the candidate you do end up hiring.

While this does take a bit more involvement up front (lose a day to write the test), I believe this is far more accurate test across various skills needed for a good developer, than just a simple fizzbuzz.


29
Jul 11

DOM text search/replace with jQuery

I recently did a quick hack to modify a bunch of text (phrases) on an already rendered HTML page. It was inconvenient to manually select single elements and modify the text – what I needed was a global search/replace.

Turns out it’s quite easy to build one, so I did. I created a jQuery plugin that can go through all text nodes inside an element, match them against a fixed string or a regular expression, and replace it. The replacement can be a fixed string, a regular expression replacement, or a result of a function. Functions can also be (ab)used to modify the element beyond just changing the text.

You can get the plugin from GitHub, and see it in action on JSFiddle. In case anyone cares, I’m releasing it to Public Domain. It should work across all browsers, although it can be quite slow on big, heavy pages with a lot of text.

Beyond quick hacks, this plugin is quite useful for things like page translation, simple A/B tests and other uses where you need to manipulate text based on its content, not the page structure.


09
Jul 11

A CLI runner module for Python

Recently I had to write several Python scripts to be run from command line or cron. They didn’t need elaborate parameter parsing, so I didn’t bother with optparse or argparse modules. I just needed something to get the strings from the command line, interpret the first one as a command, and the rest as the parameters.

I happen to use this pattern for CLI utilities a lot, so at some point I abstracted it in a small module that does it for you automatically: clirunner.

The module exports just one class, CLIRunner, which you need to extend and add methods to it – one method for each command. The runner will take care of exposing them as commands, making sure they’re called with the right number of arguments, and provide help to the user. Class and method docstrings are used for the help info.

CLIRunner does this by using the standard inspect module, which makes it easy to have code poke at itself, look up methods, docstrings and various other interesting introspection bits.

An example

Here’s a simple example:

from clirunner import CLIRunner
class HelloWorld(CLIRunner):
    "A simple Hello World application."
    def hello(self):
        "Print standard greeting."
        print "Hello World!"

if __name__ == '__main__':
    HelloWorld()

gives:

$ python hello.py
HelloWorld - A simple Hello World application.
Usage: hello.py COMMAND [ARGS...]
Commands:
    hello - Print standard greeting.

The code is open source, available on GitHub. Use it, fork it, send pull requests.


25
Jun 11

Currying in Javascript

Javascript has somewhat strange scoping rules that can catch you unaware. Here’s a typical example:

function test() {
   for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i);
        }, 1000);
   }
}
test();

This prints “0 1 2 3 4“, each number after a second, right? Wrong. What it actually outputs is “5 5 5 5 5“. Why? Because the callback function keeps a reference to i, which gets incremented to 5 long before any of the calls are made.

This is unfortunate because setting up a callback from a loop is often used in Javascript. How to work around this? There are basically two methods.

The first is wrapping the callback setup within another anonymous function, and then passing the variable as a parameter, which will effectively copy it:

   for (var i = 0; i < 5; i++) {
        (function(i) {
            setTimeout(function() {
                console.log(i);
            }, 1000);
        })(i);
   }

It works, but is rather ugly.

The second way is to add a parameter to the callback, and then curry the parameter, so it’s immediately bound and the value copied (thanks to @mreow for pointing it out). This achieves more or less the same effect as before, but is hopefully a bit more readable:

   for (var i = 0; i < 5; i++) {
        setTimeout((function(n) {
            console.log(n);
        }).bind(undefined, i), 1000);
   }

Hm. Right. Not much more readable. But, we can improve on it by creating a helper method (which will, presumably, be useful beyond this one case, so the added complexity is worth it):

function curry(val, fn) { return fn.bind(undefined, val); }
function test() {
   for (var i = 0; i < 5; i++) {
        setTimeout(curry(i, function(n) {
            console.log(n);
        }), 1000);
   }
}
test();

Now, that’s hopefully a bit cleaner. The curry function binds the value as the first parameter (the undefined there is because we don’t bind it to an object – see the bind documentation for details).

Currying is probably confusing at first sight, so here’s another example:

function curry(val, fn) { return fn.bind(undefined, val); }
function plus(a, b) { console.log(a + b); }
var plus2 = curry(2, plus);
plus2(3);

We first create a function that adds two numbers. Then, we curry that function binding value of “2″ as the first argument, and get another function, “plus2″. Then, we can call that function providing only the second argument. The end result is “5″.


24
Jun 11

Tracking down deprecation warnings in Python

A lot of Python libraries or frameworks (for example, Django) use DeprecationWarning as a non-fatal way of warning the developer that some feature is about to go extinct and they should modify their code to not use it.

Trouble with the warnings not being fatal is, you don’t get that nice traceback telling you exactly where it was called. So unless you’re debugging your own recent code, it’s a bit of challenge to track it down.

Enter warning control arguments in the Python command line. To simply turn all warnings into fatal:

  python -W error program.py ...

You can also achieve fine-grain control (or choose to ignore or do something else with the warnings) – more details over at the warnings module documentation.

(Side note: I needed this to track down usage of Django deprecated messaging API in 1.3. Turns out, it’s used by the admin. Yay).