Wildly Inaccurate http://wildlyinaccurate.com Web development, beer, and general geekiness Tue, 08 Apr 2014 13:09:05 +0000 en-US hourly 1 http://wordpress.org/?v=3.9 Defining readable code http://wildlyinaccurate.com/what-makes-code-readable http://wildlyinaccurate.com/what-makes-code-readable#comments Mon, 10 Mar 2014 12:40:55 +0000 http://wildlyinaccurate.com/?p=946 Code readability is something that I often bring up during code reviews, but I often have trouble explaining why I find a piece of code to be easy or difficult to read.

When you ask programmers how to make code easier to read, many of them will mention things like coding standards, descriptive naming, and decomposition. These things actually aid in making code easier to comprehend rather than easier to read. For me, readability is at a lower level, somewhere between legibility and comprehension.

 

Legibility - Readability - Comprehension

At the lowest level is legibility. This is how easily individual characters can be distinguished from each other, and can usually be boiled down to the choice of font, as well as the foreground & background colours.

At the highest level is comprehension, which is the ease in which a block of code can be fully understood. Decomposition, naming conventions and comments are just a few of the many ways to improve comprehension.

Readability sits between these two. This level is a little harder to define, but I believe it comes down to two main factors: structure and line density.

Structure

Our brains are very good at identifying structure and patterns; we find them pleasing. In the same sense, many people find a lack of structure to be quite displeasing. The effect of structure on readability can be easily demonstrated using an excerpt from this BBC article Indian probe begins journey to Mars.

India’s mission to Mars has embarked on its 300-day journey to the Red Planet. Early on Sunday the spacecraft fired its main engine for more than 20 minutes, giving it the correct velocity to leave Earth’s orbit. It will now cruise for 680m km (422m miles), setting up an encounter with its target on 24 September 2014.

India’s mission to Mars has embarked on its 300-day journey to the Red Planet.

Early on Sunday the spacecraft fired its main engine for more than 20 minutes, giving it the correct velocity to leave Earth’s orbit.

It will now cruise for 680m km (422m miles), setting up an encounter with its target on 24 September 2014.

Without even reading the content, the version on the right should appear more pleasant. The line breaks should give you a visual cue that each paragraph, while relevant, is not directly related to its neighbours. This is important because it lets you digest the text in smaller chunks which are much easier to comprehend by themselves than one big wall of text.

Breaking up large amounts of text into paragraphs is common practice in modern writing. Unfortunately, this practice doesn’t seem to have been adopted by programmers. It’s not uncommon to see code with no more than one sequential line break.

while(index--) {
  digit = uid[index].charCodeAt(0);
  if (digit == 57 /*'9'*/) {
    uid[index] = 'A';
    return uid.join('');
  }
  if (digit == 90  /*'Z'*/) {
    uid[index] = '0';
  } else {
    uid[index] = String.fromCharCode(digit + 1);
    return uid.join('');
  }
}

The above is an excerpt from the Mozilla Persona source code. It’s only 14 lines long, but you need to really engage your brain to read and understand it. Without some sort of paragraph structure, we have no way of knowing which lines are related, so we’re forced to digest all 14 lines at once.

while(index--) {
  digit = uid[index].charCodeAt(0);

  if (digit == 57 /*'9'*/) {
    uid[index] = 'A';
    return uid.join('');
  }

  if (digit == 90  /*'Z'*/) {
    uid[index] = '0';
  } else {
    uid[index] = String.fromCharCode(digit + 1);
    return uid.join('');
  }
}

With only 2 extra line breaks, the code has been changed from a single 14-line block to three distinct blocks, with the largest being only 6 lines. With this added structure, it’s much easier to figure out what each block does: Block #1 sets the value of digit. Block #2 handles the case of digit being 57. Block #3 handles the case of digit being 90, and every other case as well. The difference may be trivial in this example, but applied to larger blocks of code this technique can save hours of time trying to read code.

There aren’t any solid rules on when to separate blocks of code. Usually you should trust your gut and split code into blocks of related lines. As a guideline though, I tend to treat the following as separate blocks:

  • Initialization & assignment
  • Control flow
  • Data transformations

Line density

Writers will often use plain language to reduce the idea density of their text. This enables readers to quickly skim over text rather than making an effort to understand complex language. Programmers can use similar techniques to reduce what I call the line density of code. Lines become dense when they contain too much logic. A good example is a complex if-statement.

if (x == 10 || x == 20 && y == 2 || y == 5)

In this example, the reader must make a significant effort to determine that there are 3 possible “truth” conditions. The reason this requires so much effort is because we are required to read the line character-by-character until we find the ||, which we know separates each condition.

if (
  x == 10 ||
  x == 20 && y == 2 ||
  y == 5
)

By moving each condition onto its own line, the overall line density is reduced, thereby reducing the mental effort required to identify the conditions.

Line density also applies to function calls which take a large number of arguments.

doSomething(longVariableName, process(anotherVariable), ['array', 'of', 'things'], getSomethingFrom(SOME_CONSTANT))

This can be made more readable by moving each argument onto a separate line.

doSomething(
  longVariableName,
  process(anotherVariable),
  ['array', 'of', 'things'],
  getSomethingFrom(SOME_CONSTANT)
)

Other factors

There are plenty of other factors involved in code readability. But as with most things, readability is entirely subjective — it’s important not to confuse it with personal preference.

Programming is an interesting mix of engineering and craft. As well as borrowing precision and discipline from engineering, we need to remember to also borrow style and ergonomics from visual design.

]]>
http://wildlyinaccurate.com/what-makes-code-readable/feed 0
HTTP status as a service http://wildlyinaccurate.com/http-status-as-a-service http://wildlyinaccurate.com/http-status-as-a-service#comments Mon, 30 Sep 2013 14:13:22 +0000 http://wildlyinaccurate.com/?p=930 Using Node.js* you can run a simple “HTTP status as a service” server. This can be useful for quickly checking whether your application handles various status codes.

var http = require('http');

http.createServer(function (request, response) {
  var status = request.url.substr(1);

  if ( ! http.STATUS_CODES[status]) {
    status = '404';
  }

  response.writeHead(status, { 'Content-Type': 'text/plain' });
  response.end(http.STATUS_CODES[status]);
}).listen(process.env.PORT || 5000);

This will create a server on port 5000, or any port that you specify in the PORT environment variable. It will respond to /{CODE} and return the HTTP status that corresponds to {CODE}. Here’s a couple of examples:

$ curl -i http://127.0.0.1:5000/500
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
Date: Mon, 30 Sep 2013 14:10:10 GMT
Connection: keep-alive
Transfer-Encoding: chunked

Internal Server Error%
$ curl -i http://127.0.0.1:5000/404
HTTP/1.1 404 Not Found
Content-Type: text/plain
Date: Mon, 30 Sep 2013 14:10:32 GMT
Connection: keep-alive
Transfer-Encoding: chunked

Not Found%

This is a really simple example, and could easily be extended to let you specify a Location header value for 30X responses.

*Well, you could use anything really. I’m just using Node.js since JavaScript is my language of choice.

]]>
http://wildlyinaccurate.com/http-status-as-a-service/feed 0
Converting Bootswatch themes to SASS/SCSS http://wildlyinaccurate.com/converting-bootswatch-themes-to-sass http://wildlyinaccurate.com/converting-bootswatch-themes-to-sass#comments Fri, 06 Sep 2013 14:24:49 +0000 http://wildlyinaccurate.com/?p=922 There’s a fairly quick way to convert Bootswatch themes to Sass (which you might want to do if you use something like sass-bootstrap).

Simply download the theme’s variables.less and run the following find/replace patterns against it:

Variables

Find (regex): @([a-zA-Z0-9_-]+)
Replace: \$$1

Mixins

Find: spin(
Replace: adjust-hue(

This is all I’ve found in the themes that I’ve tried.

]]>
http://wildlyinaccurate.com/converting-bootswatch-themes-to-sass/feed 0
Getting Internet Sharing to work on OSX 10.8 http://wildlyinaccurate.com/getting-internet-sharing-to-work-on-osx-10-8 http://wildlyinaccurate.com/getting-internet-sharing-to-work-on-osx-10-8#comments Tue, 20 Aug 2013 11:39:55 +0000 http://wildlyinaccurate.com/?p=910 I noticed that the Internet Sharing functionality didn’t work on my Macbook Air (running OSX 10.8 – Mountain Lion). This is because the Air’s DNS server (BIND) isn’t configured correctly.

For me, the fix was pretty simple. Edit /etc/com.apple.named.proxy.conf by running sudo nano /etc/com.apple.named.proxy.conf in a terminal, and change

forward first;

to

forward only;

Then turn Internet Sharing off and on again.

The annoying thing is that OSX seems to restore the BIND config the next time you turn Internet Sharing off, so you need to remember to change it each time.

]]>
http://wildlyinaccurate.com/getting-internet-sharing-to-work-on-osx-10-8/feed 0
Force Bower to clone from https:// instead of git:// http://wildlyinaccurate.com/force-bower-to-clone-from-https-instead-of-git http://wildlyinaccurate.com/force-bower-to-clone-from-https-instead-of-git#comments Fri, 16 Aug 2013 16:09:28 +0000 http://wildlyinaccurate.com/?p=905 Most Bower packages will be fetched using a git:// URL, which connects on port 9418. This can be problematic if you’re behind a firewall which blocks this port.

You can get around this quite easily by telling Git to always use https:// instead of git://:

git config --global url.https://.insteadOf git://
]]>
http://wildlyinaccurate.com/force-bower-to-clone-from-https-instead-of-git/feed 0
Dishonest comments http://wildlyinaccurate.com/dishonest-comments http://wildlyinaccurate.com/dishonest-comments#comments Wed, 07 Aug 2013 21:07:02 +0000 http://wildlyinaccurate.com/?p=865 One of my favourite Ruby Rogues episodes (What Makes Beautiful Code) has a short section where the Rogues talk about the concept of dishonest code. David Brady wrote a really good piece on this, which I highly recommend reading.

What I want to talk about is a more specific variant of dishonest code: dishonest comments.

Take this code, for example:

$('a').click(function(e) {
    e.stopPropogation();
    e.preventDefault();
});

If you’re not familiar with JavaScript events, e.stopPropogation() will stop this event from bubbling up to other event handlers. Now, what if somebody decides that the event should bubble up? They might do something like this:

--- a/example.js
+++ b/example.js
@@ -1,4 +1,4 @@
 $('a').click(function(e) {
+    // Let the event bubble up to the next handler
-    e.stopPropogation();
     e.preventDefault();
 });

This is pretty common practice; a developer will leave a comment so that the next person understands why the e.stopPropogation() is gone.

So far this isn’t too bad. But what happens when somebody changes their mind again, and doesn’t want the event to bubble up anymore? Quite often, this is what happens:

--- a/example.js
+++ b/example.js
@@ -1,4 +1,5 @@
 $('a').click(function(e) {
     // Let the event bubble up to the next handler
+    e.stopPropogation();
     e.preventDefault();
 });

The e.stopPropogation() call is added back in, right where it was before. You can see the problem here: the comment explaining that the event will bubble up is still there.

A lot of developers tend to ignore comments in code, especially comments that were written by somebody else. Modern text editors and IDEs are partly to blame for this, since their syntax highlighting tends to de-emphasise comments by greying them out.

$('a').click(function(e) {
    // Let the event bubble up to the next handler
    e.stopPropogation();
    e.preventDefault();
});

What we’ve ended up with is a comment which says one thing, and some code which does something entirely different. This is surprisingly common — most codebases are absolutely littered with dishonest comments.

The example I’ve given above might seem contrived, but this is an entirely real —although somewhat simplified— example of some code that I had to debug recently.

Dishonest comments can confuse even the most experienced developers, and make debugging much more difficult than it needs to be. Figuring out what one line of code is supposed to do can turn into an hour of trawling through version control logs and diffs.

The worst part about dishonest comments is that the problems they cause aren’t immediately obvious. Unit tests won’t pick them up. A full regression test won’t find them. Once they’re committed to the codebase, they remain hidden right up until the point where you realise that they’re lying to you.

So really, the only way to avoid dishonest comments is to simply not write them in the first place.

In the Ruby Rogues episode I mentioned at the start of this post, there’s a brief discussion about the idea that comments are a code smell. This idea is hotly debated. However, I do believe that treating comments as a code smell can help you to identify dishonest comments before they become a problem.

I think this ends up coming back to the way that syntax highlighting hides comments from us. It’s really difficult to spot dishonest comments because we’ve trained our brains to focus on the bright & colourful text, and ignore the dull grey text.

Greyed-out comments

If you opened this file to make some changes, chances are you wouldn’t even notice the comments, let alone figure out that they are all lies. But what if the comments stood out more?

I’m currently experimenting with my own variation of the Monokai colour scheme which draws comments in a bright colour.

Bright comments

Suddenly the comments stand out. They even stand out more than most of the actual code in this file. To me, this is a good thing because comments should only be there to say something important that the code can’t say by itself. If there is a comment in the code, I want it to stand out because it must be telling me something really important.

Having the comments stand out more also makes it much more obvious when there are too many comments. Usually, seeing a lot of comments tells me that either:

  1. Most of these comments are unnecessary, or,
  2. The code needs to be refactored to be self-documenting

If the comments are unnecessary, they can be removed. If the code can be more self-documenting, then the comments that were documenting it can be removed. Either way, you end up with less comments, and less dishonesty.

How you deal with dishonest comments in your codebase is up to you. In the end though, it’s down to you and your team to be more thoughtful about the comments that you write. If an honest comment can be turned into a dishonest comment simply by changing the code around it, then you probably need to re-think whether that comment is necessary.

]]>
http://wildlyinaccurate.com/dishonest-comments/feed 0
Don’t use Git’s autocorrect feature http://wildlyinaccurate.com/dont-use-gits-autocorrect-feature http://wildlyinaccurate.com/dont-use-gits-autocorrect-feature#comments Wed, 07 Aug 2013 14:40:12 +0000 http://wildlyinaccurate.com/?p=862 Quite often I’ve accidentally typed “git” twice. Usually this is fine, and Git just does something like this:

$ git git diff
git: 'git' is not a git command. See 'git --help'.

Did you mean this?
    init

But I recently turned on Git’s autocorrect feature, to see what it was like (git config --global help.autocorrect 1). The results were… interesting:

$ git git diff
WARNING: You called a Git command named 'git', which does not exist.
Continuing under the assumption that you meant 'init' in 0.1 seconds automatically...
fatal: internal error: work tree has already been set
Current worktree: /nfs/personaldev/vagrant/mobileweb-v2
New worktree: /nfs/personaldev/vagrant/mobileweb-v2/diff

This is really bizarre behaviour. The fact that it wants to autocorrect it to git init is sort-of okay. But rather than giving me the option to confirm that this is what I want, Git gives me a whole 0.1 seconds to hit Ctrl+C before it automatically runs the command for me.

Thankfully, git init isn’t a very destructive command. I was lucky that the only side effect of this was that Git created a new directory called diff. I can’t help but wonder what would’ve happened if Git decided to autocorrect to a more destructive command like reset, checkout, or gc.

The lesson here? Don’t use Git’s autocorrect. It really sucks.

]]>
http://wildlyinaccurate.com/dont-use-gits-autocorrect-feature/feed 2
Installing PHP on Debian without Apache http://wildlyinaccurate.com/installing-php-on-debian-without-apache http://wildlyinaccurate.com/installing-php-on-debian-without-apache#comments Thu, 01 Aug 2013 17:52:36 +0000 http://wildlyinaccurate.com/?p=838 When you apt-get install php5 on a Debian/Ubuntu server, you’ll notice that APT will automatically install a bunch of apache2 packages as well. This can be pretty annoying if you’re planning on using another web server (or no web server at all).

If you take a look at the package dependencies (Debian/Ubuntu) you’ll see why this happens – php5 needs one of either libapache2-mod-php5, libapache2-mod-php5filter, php5-cgi, or php5-fpm. APT doesn’t care which package it installs; it just picks the first package that satisfies the dependency, which is why you get the apache2 packages.

You can get around this by installing one of the other dependencies before php5. For example, apt-get install php5-fpm php5 or apt-get install php5-cgi php5.

]]>
http://wildlyinaccurate.com/installing-php-on-debian-without-apache/feed 2
Using SSH agent forwarding with Vagrant http://wildlyinaccurate.com/using-ssh-agent-forwarding-with-vagrant http://wildlyinaccurate.com/using-ssh-agent-forwarding-with-vagrant#comments Thu, 01 Aug 2013 10:18:35 +0000 http://wildlyinaccurate.com/?p=830 Sometimes you’ll want to use your local SSH keys on your Vagrant boxes, so that you don’t have to manage password-less keys for each box. This can be done with SSH agent forwarding, which is explained in great detail on Unixwiz.net.

Setting this up is fairly straightforward. On the host machine, you need to add the following to ~/.ssh/config (which you should create if it doesn’t exist):

host your.domain.com
    ForwardAgent yes

You need to replace your.domain.com with either the domain or the IP address of your Vagrant box. You can wildcard this with host *, but this is a really bad idea because it lets every server you SSH to access your keys.

Once you’ve done that, just run ssh-add to ensure you ensure your identities are added to the SSH agent.

Now, add the following to the config block in your Vagrantfile:

config.ssh.forward_agent = true

That’s all it takes. You can make sure it worked by comparing the output of ssh-add -L on both the host machine and the guest box.

]]>
http://wildlyinaccurate.com/using-ssh-agent-forwarding-with-vagrant/feed 3
Worst fonts for programming http://wildlyinaccurate.com/worst-fonts-for-programming http://wildlyinaccurate.com/worst-fonts-for-programming#comments Wed, 17 Jul 2013 16:07:13 +0000 http://wildlyinaccurate.com/?p=805 There are plenty of discussions about which font is the best for programming. The problem is, there are so many “best” fonts that it’s difficult to choose one. Rather than have an exhaustive list of “best” fonts for programming, wouldn’t it be easier to simply know which fonts to avoid?

Brush Script MT

This font was created in 1942 by Robert E. Smith. It’s designed to look like the characters have been handwritten with an ink brush. This font will make you feel right at home if you grew up writing your code with an ink brush. Otherwise, don’t use it.

Brush Script MT

Chiller

A relatively modern font (1995), Chiller is supposed to be very legible even at small sizes. This font is great for giving your code that “spooky” feel. However if you prefer emotionless, monospaced fonts, Chiller is probably not for you.

Chiller

Comic Sans MS

By far the most loved font on the web, Comic Sans has been bringing joy to peoples’ lives since its inception in 1994. Coding in Comic Sans is fun, and reading code in Comic Sans is even funner-er. Unfortunately, some people don’t like Comic Sans, so you should avoid using it unless you enjoy being ridiculed by your colleagues.

Comic Sans MS

Impact

Created in the Swinging Sixties by a fellow named Geoffrey Lee, Impact was intended for headlines. Why should headlines be the only text with emphasis, though? Using Impact will give your code the emphasis it deserves by making every single line a headline. The downside is that prolonged exposure to Impact can cause developers to read everything in a yelling voice. If this is a problem for you, avoid using this font.

Impact

]]>
http://wildlyinaccurate.com/worst-fonts-for-programming/feed 3