Skip to content

Conventions

davidabrahams edited this page May 1, 2018 · 26 revisions

Table of Contents

Asserts

We have created a standard function that checks to make sure a given statement is true and, if not, throws an error with a specified message.

All assert messages should state the current state of things if an error is thrown and should in almost all cases include the word not.

Examples

If a variable x must be greater than or equal to variable y:

assert(x >= y, 'x is not greater than or equal to y');

If a variable x must be even:

assert(x % 2 === 0, 'x is not even');

Note that in this example, the assert does not say x is odd.

Classes

Methods

Docstrings

See Functions: Docstrings.

New-Lines

Use two new-lines between class methods.

Examples

The class below has two new-lines between its methods.

class Doge {
  constructor(name) {
    ...
  }


  suchBark() {
    ...
  }


  muchWag() {
    ...
  }


  wow() {
    ...
  }
}

Comments

New-Line vs. In-Line

Prefer in-line comments to new-line comments, unless:

  • the in-line comment would push the line over the 100 character limit.
  • you are commenting an entire scope, such as an entire if statement, for loop, or function.

Examples

The first comment below is a new-line comment, because it documents the entire for loop scope even though it could fit as an in-line comment on the same line as the for loop.

// Double baz bar times
for (let foo = 0; foo < bar; foo++) {
  baz *= 2; // double baz
}

Capitalization

Capitalize new-line comments. Do not capitalize in-line comments

Function Docstrings

See Functions: Docstrings.

Indentation

If a comment requires multiple lines, indent all lines after the first line by one level. This includes function-level documentation.

Examples

The new-line comment below spans multiple lines and so indents by one level after the first line.

// For each of the 6 edges, either merge together the edges that lay in line with it (ie, this
//   edge connects two edges separated by one tile) or break them apart (if an edge lays across an
//   edge in the unmerged graph which doesn't exist)

The function-level comment below indents by one level for multi-line entries.

/**
* @param {(number|null)} chatData.from - the index of the player who sent the message or null if
*   the message is a system message
* @param {string} chatData.message - the message sent
* @param {string} chatData.to - the recipients of the message ('all', 'team', or 'group')
* @param {string} chatData.c - the hex representation of the color to change the text to (for
*   example for flair awards)
* @param {boolean} chatData.mod - true if sender of message is a mod
*/

Commit Messages

  • Precede each message with the issue number and a colon.
  • Start each commit message with a verb in the simple present tense.
  • Refer to class methods in the format of ClassName.methodName().

Examples

The commit message below starts with the issue number and a colon, followed by the commit description.

180: add chat function

The commit message below uses the simple present tense of the verb add (not added or adding).

127: add new feature

The commit message below refers to a class method in the format of ClassName.methodName().

192: update Fruit.eat() to run more efficiently

Functions

Docstrings

Follow the JSDoc convention for function-level comments.

Examples

See JSDoc's conventions on param and return.

Names

Err on the side of having function names specify what the input type(s) are, and what the resulting function does. A docstring and appropriate @param, @returns tags are appropriate substitutes for a self-documenting function name, though self-documenting code is preferred.

New-Lines

Functions should have two new-lines between them.

Tests

Nesting

  • All tests should be nested by the function that they are testing, even if there is only a single test within the nested scope. This makes it easier to add additional tests later.
  • Only the inner-level tests themselves should be ended with test.end(). The outer-level test scope should not be ended.

Examples

The test below is nested within the function name scope, even though there is only a single test within the nested scope.

test('functionName()', tester => {
  tester.test('test case description', t => {
    ...
    t.end();
  });
});

Below, only the inner-level test scopes are ended (the outer level tester scope is not ended) and each inner-level test scope is separated by a new-line.

test('functionName()', tester => {
  tester.test('test case 1 description', t => {
    ...
    t.end();
  });

  tester.test('test case 2 description', t => {
    ...
    t.end();
  });

  tester.test('test case 3 description', t => {
    ...
    t.end();
  });
});

New-Lines

  • Tests should follow the format of setup, asserts, and cleanup (with one new-line between each of these three sections).
  • Inner-level test scopes should be separated by a new-line.
  • Outer-level test scopes should be separated by two new-lines.

Examples

The test below shows the sections, each separated by a single new-line.

test('functionName()', tester => {
  tester.test('test case 1 description', t => {
    // Setup
    const mockVar = sinon.spy();
    FileNameReqireAPI.__Rewire__('var', mockVar);

    // Asserts
    functionName();
    t.is(var, 7);

    // Cleanup
    FileNameRewireAPI.__ResetDependency__('var');
    t.end();
  });
});