Server-side JavaScript

Capitalisation

We use camelCase for variables in all cases, except:

  • ClassNames, and Actions are capitalised.
  • CONSTANTS_ALL_CAPS, and declared at the top of the file.

Naming things

Name things carefully. They should be descriptive, but not too long.

Never abbreviate any word, even if it’s a temporary variable, because your abbreviation is less legible and could very likely be confused with another concept, eg school, not sch. Write things out in full, eg alternativeSpecialThing not AST.

You probably shouldn’t include the type of the thing in the name. eg. in

    var SupervisorApplication = P.form("supervisor-application", "form/supervisor-application.json")

SupervisorApplication doesn’t need a Form suffix, it’s obvious because you’ve assigned it from P.form().

Be specific. eg. CanEditSpecialText, not just Allowed.

API codes and other meaningful strings

Haplo APIs make use of string identifiers – service names, feature names, actions, schema API codes, URLs, etc. all use significant strings as identifiers. These should:

  • always be lower case
  • API codes use dashes
  • URLs use dashes
  • Where a Service or Action is specific to a plugin, it should be prefixed with the plugin name, and use underscores (to match plugin names which must be valid JavaScript symbols), eg. plugin_name:what_it_does
  • Features, and a Service or Action which advertises or implements a generic capability, should be namespaced using the usual conventions with colons to separate, eg. hres:repository:exciting-action.

Code Layout

    // Space after the condition and not before
    // Braces start on the same line as condition
    if(thing) {
        // ...
    } else {
        // ...
    }

Indent with 4 spaces. Tabs should not be used.

There should be whitespace around most operators, including addition and subtraction:

    x = a + b;

In function definitions, include spaces between arguments and after the argument list, and assign functions to named variables with var at the top level.

    var egFunction = function(arguments, have, spaces) {
        // My code
    };

Never nest ternaries.

    // DON'T DO THIS
    var x  = a ? (c ? d : e ) : b;

Blank lines in code should should be significant, separating sections of code that have a different purpose, like paragraphs in prose.

When adding separator comments in files, add a note in the separator about the content of the following section of code. The last - should be in the 78th column, regardless of the indentation.

    // ----------------------------------------------------------------------
    // Public API for XYZ                                    78th character ^

Comments should go next to code if short, or on the line above if it’s longer than will fit naturally on a normal width text editor window.

But comments shouldn’t be necessary. When they are, they should describe the “why” behind the code they annotate – the “what” should be read from the code through using meaningful variable names throughout.

Declare each variable on a new line ending with a semicolon, with a new var keyword (or let, if using ES6 features).

    // DON'T DO THIS
    var foo = "test",
        bar = 42,
        fizz, bang;
    // INSTEAD, DO THIS
    var foo = "test";
    var bar = 42;
    var fizz;
    var bang;

ES6 features

Haplo plugins uses the Rhino JavaScript interpreter, which doesn’t have the full set of ES6 features, and others are not preferred in this style guide.

Also note that a lot of plugin code was written before ES6 features were available in Rhino. To avoid spurious changes and errors these files have not been updated to use these features. We aim to always to match the style within the file, so each JavaScript file should either use ES6 features throughout or not at all.

Arrow functions

  • Don’t use them for top level functions. Only use them inside others, primarily as iterators, or to pass to other functions
  • Always put the brackets around the input parameters
  • Go for clarity – no need to use curly brackets for single return values
    let doubled = _.map([1, 2, 3, 4, 5], (number) => number * 2);

Method definitions

There’s no need to write the function keyword in object definitions – it is preferred to use method definitions where appropriate;

    let something = {
        hello(a, b) {
            console.log("hello", a, b);
        }
    };

let and const

Prefer to use var for top level variables, because the hoisting is useful in allowing you to lay out a file sensibly without being concerned by variable definition order.

let should be used for everything below top level, except for variables that will be defined once and never changed, which should use const.