A universal style guide

January 10, 2016

In my opinion, a style guide is essential to any open source project or project with multiple contributors.

Ideally, a style guide should consist both of a specification and a tool to check and apply the styling to source files. Good examples are go fmt or pep8.

But moreover, I believe a style guide should be universally applicable, no matter the programming language.

What follows is my personal, universal style guide. Of course, those are only guidelines and the rules might need to be broken in a few cases. It includes a few rules for writing simple and maintanable code as well.

General styling

  • 4 spaces for indentation. This is a controversial topic, but 4 spaces tend to be more readable and aligns nicely with Pythons or Rubys def.
def helloWorld
    "Hello, World!"
end
  • 80 characters line length. It’s the default width for most terminals and narrow code is more readable. The only exception to this rule are strings which can’t be broken up.
text := "Anyone is free to copy, modify, publish, use, compile, sell, or " +
        "distribute this software, either in source code form or as a " +
        "compiled binary, for any purpose, commercial or non-commercial, " +
        "and by any means."
  • After a line wrap, Function parameters should align with previous parameters.
#!/bin/bash
sudo apt-get -qy install astyle bison build-essential cabal-install-1.22 \
                         cmake command-not-found curl
  • Double quotes for strings
console.log("Hello, World");
  • Keywords are followed by a space. Operators have spaces before and after them. In general, each special character should have spaces around it. Exceptions to this rule: (, ), [, ] and !.
if err != nil {
    http.Error(w, err.Error(), http.StatusBadRequest)
}
  • Avoid parentheses if possible. We don’t want to end up with something as unreadable as Lisp.

Logical paragraphs

  • Variables should be grouped together in blocks.
  • The members of a block should be aligned by =, : or a similar symbol.
  • Blocks, methods and classes are be separated by an empty line.
  • Everything should be alphabetically ordered. This includes: Variables, Classes, Methods, Lists, Maps, etc.
  • Files should have the following structure:
    1. Imports
    2. Global variables
    3. Classes
    4. All other methods / functions.

Classes

  • Classes are not longer than 100 lines. Blank lines and comments don’t count.
  • Avoid getters, setters and properties. Try to use encapsulation instead.

Methods

  • Methods should be no longer than 5 lines. This enforces us to write clean code. Blank lines and comments don’t count.
  • Methods take no more than four parameters.
  • Methods should only have one level of identation. If you need more, your function is probably too complicated.
  • Avoid the else keyword. This prevents if-else chaining.

Naming

  • Names should be descriptive but short.
  • Don’t abbreviate names.
  • Names should be written in camelCase.

Documentation

  • Always use multiline comments for Documentation. Single line comments should be reserved for actual in-line comments.
  • Documentation should always start with the exact name of a class or method.
  • Multiline comments should open and close on a separate line.
/*
 * example does this and that...
 */
function example() {
    log("This and that")

    // This is a useful comment about our choice of callback
    callback()
}

Miscellaneous

  • Wrap primitives in a classes. There is a reason you want to use primitives, so it’s probably important enough for its own class. See Primitive Obsession
  • No unused variables
  • Always treat error variables.
  • No trailing whitespaces. They’re evil!
  • Each file should end with a blank line. It’s the POSIX standard.
  • No multiple blank lines

And the most important rule of them all:

Readability trumps compactness