Chris Ashton

The five-line rule

You’ve probably heard of the five-second rule. If you drop something tasty on the floor, it’s OK to pick it up and eat it provided you pick it up within five seconds of dropping it, since the bacteria won’t spread through your food and spoil it in such a short amount of time.

This is nonsense, of course – food is already riddled with the bacteria of the surface it lands on the moment it touches it, and it’s at your discretion to weigh up the risks of the bacteria, the hassle of retrieving the food, and the tastiness of the food itself (and perhaps other non-functional requirements, such as how hungry you are, whether anyone is watching, whether you have any backup food, etc). Picking an untainted burger off the recently cleaned kitchen floor is fine; scooping a mostly-eaten trifle off the carpet into your hands is probably not.

Anyhow, generally speaking, you’re allowed to pick up food within five seconds of dropping it: the food is still good. In the same way, if I can understand what your file or class is doing by reading the first five lines, it’s probably pretty good code.

Here, the number five is chosen to fit nicely with my metaphor, but depending on the language, you may need to boost this to 10, 15, or 30 lines. I’d expect a Python script to tell me what it’s doing in under five lines (this is perfectly achievable, as a number of Python entries on ProgramInATweet show). A Java class, requiring import statements, attribute declarations and other setup work may require significantly more.

The point is, the file should be written in such a way as to minimise the amount of effort a developer has to expend on finding out its purpose. Like all developers, I’m lazy; if the file is useless to me, I don’t want to have to read any of its contents to come to that conclusion. If I do have to read some of its contents, at least make it a smaller, more achievable task.

Consider this code snippet, taken from the JSHint library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env node
/*jshint shelljs:true */

"use strict";

var browserify = require("browserify");
var bundle = browserify();
var path = require("path");
var version = require("../package.json").version;
require("shelljs/make");

var distDir = path.join(__dirname, "../dist");
var srcDir = path.join(__dirname, "../src");

if (!test("-e", distDir))
mkdir(distDir);

Read the first five lines. What does it tell you? Do you know what this script is for? Read on another 5 lines. Are you enlightened yet? How about after 15 lines?

Disclaimer: I love JSHint as a pre-processing tool, and this isn’t meant as an attack on their contributors – but it was the first bit of code that I came across while writing this that served as a suitable example of violating the five-line rule. These first few¬†lines of code give me no indication as to what the file is responsible for (to be honest, the rest of the file isn’t much help either).

You could argue that the file is called “build”, and that gives enough of an idea as to the code’s purpose. However, sometimes due to the restrictions of the platform, or the naming conventions of the tech team, the filename itself can’t be very descriptive. Filename aside, WHAT is it building? How should I use it? Should I not use it at all – is it for internal use? When should it be run? What are its inputs and outputs?

A quick scan of the documentation doesn’t answer my questions, but even if there is an answer tucked away somewhere, hiding answers away in remote FAQs is not a developer-friendly solution to the simple question: “what is this file for?”

Sometimes, we can achieve this easily enough in code:

1
2
3
4
<!--?php &lt;br ?--> $ip = get_user_ip();
if (!not_banned($ip)) {
download_video();
}

Here it’s fairly obvious in just five lines that we have some sort of location-restricted video that the user is trying to download. The script gets the user’s IP address, checks the IP address against a blacklist, and if the video is allowed to be displayed where the user is located, it is downloaded. This procedural code is not perfect, but it is self-documenting, and it tells you what the script is doing. We don’t need to scroll down further and see the implementation of the functions to understand what is happening.

Other platforms, languages or scenarios might require a different solution, e.g. a header comment at the top of the file describing the file contents. I’ve got a fairly good example of this in the Ashton API:

1
2
3
4
<!--?php &lt;br ?--> // this should run every 10 mins to create a json file with the info, as
// we don't want to have to query linkedin and twitter every time we load the site.
require_once('twitter/twitter.php');
require_once('linkedin/linkedin.php');

Even this isn’t really descriptive enough, but it does give you an indication that this is a script that should be called in a cronjob, it creates information in JSON format and writes it to a file, and it has external dependencies. Without the comment, and without procedural code, I might otherwise have had to read the whole file to reach the same conclusion. If I’m not interested in the contents or creation of the JSON file I can save my time and look elsewhere.

Next time you finish writing a file, try and imagine coming back to it as someone else. Read the first few lines. Do you know what the intention of the file is? If not, add a descriptive comment at the top – or better still, refactor. Remember the five-line rule.