UNPKG

hapi

Version:

HTTP Server framework

679 lines (489 loc) 13.8 kB
# Coding Conventions ## JavaScript ### Language #### Semicolon - Always end statements with `;` ```javascript // Right console.log('even when not required'); // Wrong console.log('even when not required') ``` #### Variable declarations - Declare on first use, not at top of function - Do not chain declarations unless inside `for` parentheses (repeat `var` for each variable in a separate statement) - Give descriptive names - Do not use similar names or synonyms for different variables unless following a convention - `for...in` iterators should use descriptive names - `for` iterators should use single character names - Use combination of plural for array and singular for each item in the array - Use camelCase, never underscores - Avoid using numbered variables (e.g. i1, i2, i3) #### Scope - No implicit or single statement scopes - All scopes must be wrapped in `{}` ```javascript // Right if (condition) { return; } // Wrong if (condition) return; if (condition) return; ``` #### For loops - Iterator variable should be declared inside the `for` parentheses, unless already defined - Use `for` with arrays, `for...in` for objects (and always check `hasOwnProperty()`) - When iterating over a fixed or calculated size, assign size to a variable inside the `for` declaration and use iterator variable name with `l` suffix - Always `++i`, never `i++` ```javascript // Right var name = 'john'; for (var i = 0, il = name.length; i < il; ++i) { console.log(name[i]); } // Wrong var position; var name = 'john' ; for (position = 0; position < name.length; position++) { console.log(name[position]) ; } ``` #### Prototype members - Prefix private members with `_` ```javascript Example.prototype.method = function () { this.public = 'external'; this._private = 'internal'; }; ``` - Define `self` for passing `this` into nested functions ```javascript Example.prototype.method = function () { var self = this; call(123, function (err) { self.display(err); }); }; ``` #### Function declaration - Declare functions via assignment ``` javascript // Right var method = function () { }; // Wrong function method() { } ``` #### Enforcing new on Constructor - Use this.constructor === to check if a constructor function was called with new ```javascript // Right Utils.assert(this.constructor === Server, 'Server must be instantiated using new'); // Wrong Utils.assert(this instanceof Server, 'Server must be instantiated using new'); ``` ### Style #### Whitespace - Always spaces, never tabs - 4 spaces indents - No trailing whitespace at end-of-line ```javascript // Right if (test) { if (value === 12) { console.log('result'); } } // Wrong if (test) { if (value === 12) { console.log('result'); } } ``` #### String literals - Always `'` never `"` ```javascript // Right var string = 'text in single quotes'; // Wrong var string = "text in single quotes"; ``` #### Newlines - Two empty lines between module functions or assignments (end of function to comment about next function) ```javascript exports.get = function () { // Some code }; // 1 // 2 /** * jsDoc comment */ internals.utility = function () { //Some code }; ``` - Newline after `{` except for inlined or empty objects - Inline an object when it improves readability and unlikely to change often - No inline object in assignment unless empty ```javascript // Right if (condition) { execute(value, { strict: true }); } if (condition) { var options = { strict: true }; execute(value, options); } var empty = {}; // Wrong if (condition) { execute(value, { strict: true }); } if (condition) { var options = { strict: true }; execute(value, options); } var empty = { }; ``` - Newline after `}` - Only exception is when followed by `,`, `;`, `);` which must be followed by a newline - Includes before `else`, `catch`, etc. - Empty line after `}` if not last statement in scope ```javascript // Right if (condition) { value = { func: function () { console.log('example'); }, message: 'hello' }; execute(value, function (err) { console.log(err); }); } else { console.log('otherwise'); } // Wrong if (condition) { value = { func: function () { console.log('example'); }, message: 'hello' }; execute(value, function (err) { console.log(err); } ); } else { console.log('otherwise'); } ``` - Empty line after `{` - Following a multi-line condition - In function scope declarations ```javascript // Right exports.method = function () { if (condition) { if (otherCondition) { console.log('sometimes'); } if (result && result.code === 200) { console.log('special case'); } console.log('always'); } execute(123, function (err) { console.log(err); }); var empty = {}; }; // Wrong exports.method = function () { if (condition) { if (otherCondition) { console.log('sometimes'); } if (result && result.code === 200) { console.log('special case'); } console.log('always'); } execute(123, function (err) { console.log(err); }); var empty = { }; }; ``` - No empty line before end of scope ```javascript // Right if (condition) { if (otherCondition) { console.log('done'); } } // Wrong if (condition) { if (otherCondition) { console.log('done'); } } ``` #### Spaces - Use one and only one space (when required) ```javascript // Right var value = calculate(1, 3); // Wrong var value = calculate(1, 3); ``` - No space between function name and `(` ```javascript // Right function example() { return value; } var key = example(); // Wrong function example () { return value; } var key = example (); ``` - No space after `(` or before `)` ```javascript // Right execute('order', 34); if (result === 'ok') { console.log('success'); } // Wrong execute( 'order', 34 ); if ( result === 'ok' ) { console.log( 'success' ); } ``` - No space before object key `:`, always after object key `:` ```javascript // Right var obj = { a: 1, b: 2, c: 3 }; // Wrong var obj = { a : 1, b :2, c:3 }; ``` - No space before `;`, always after `;` if not end-of-line ```javascript // Right var name = 'john'; for (var i = 0, il = name.length; i < il; ++i) { console.log(name[i]); } // Wrong var name = 'john' ; for (var i = 0, il = name.length;i < il ;++i) { console.log(name[i]) ; } ``` - Always space after reserved keywords (`if`, `else`, `for`, `return`, `function`, etc.) ```javascript // Right for (var book in books) { if (books.hasOwnProperty(book)) { console.log(book.name); } } // Wrong for(var book in books) { if(books.hasOwnProperty(book)) { console.log(book.name); } } ``` - Always space after `{` and before `}` in inlined object - No space for empty objects `{}` - One space for empty functions `{ }` ```javascript // Right var user = { name: 'john', email: 'john@example.com' }; var empty = {}; var callback = function () { }; // Wrong var user = {name: 'john', email: 'john@example.com'}; var empty = { }; var callback = function () {}; ``` - No space after `[` and before `]` in inlined arrays ```javascript // Right var numbers = [1, 2, 3]; // Wrong var numbers = [ 1, 2, 3 ]; ``` - Always space after `//` ```javascript // Right // Some comment // Wrong //Some comment ``` - No space before `,`, always after `,` unless end-of-line ```javascript // Right var numbers = [1, 2, 3]; var user = { name: 'john', email: 'john@example.com' }; for (var i = 0, il = name.length; i < il; ++i) { console.log(name[i]); } // Wrong var numbers = [1,2 ,3]; var user = { name: 'john',email: 'john@example.com' }; for (var i = 0,il = name.length; i < il; ++i) { console.log(name[i]); } ``` - Always space before and after operators, unless following ident or end-of-line ```javascript // Right var a = 1 + 3; var b = 'john' + ' ' + 'doe'; // Wrong var a=1+3; var b='john'+ ' '+ 'doe'; ``` #### Commas - Never begin a line with `,` (always at the end of the previous line) ```javascript // Right execute('some error message', 12345, this); // Wrong execute('some error message' ,12345 ,this); ``` #### Operators - Never begin a line with an operator (always at the end of the previous line) ```javascript // Right var message = 'Hello ' + 'Steve, ' + 'How are you?'; if (value === 'hello' && result === 'ok') { console.log('yes'); } // Wrong var message = 'Hello ' + 'Steve, ' + 'How are you?'; if (value === 'hello' && result === 'ok') { console.log('yes'); } ``` #### Comments - Always use `//` unless it's a jsDoc declaration or license header - Always begin sentences with an upper case - No trailing `.` unless comment contains multiple sentences - Formal style, consistent voice, no humor, present tense - No developer name or other personal notes - No TODOs - Line - Provides narrative for the following single code line (or single statement broken for readability) - One line of comment only - One empty line before and none after the comment line - No empty line before when following `{` unless other rules require it ```javascript function execute() { // Initialize state var position = 0; if (condition) { // Return message return 'hello'; } } ``` - Segment - Provides narrative for the following code section (one or more lines of code, with or without line breaks) - One or more lines of comments - One empty line before and one after comments block ```javascript function execute() { // Print each book's name for (var book in books) { // Check for valid properties if (books.hasOwnProperty(book)) { console.log(book.name); } } } ``` - Note - Explains the behaviour of a single code statement (can be broken into multiple lines) - Used to document unexpected behaviour or non-standard practice - Appears immediately at the end of the line (or statement) it describes, following whitespace to separate it from code block ```javascript function execute(value) { if (value !== null && value !== undefined) { // Explicit check as 'value' can be 0 console.log(value); } } ``` #### Multi-line statements - Statements should only be broken into multiple lines to improve readability - Break statements if they are longer than 150 characters long - No empty lines in the middle of a single statement - Indent multi-line statements - Conditions should be indented to the first character of the condition in the first line ```javascript if (result && result.status && result.status.code === 200) { console.log('success'); } ``` - Variable should be indented to the first character of the value in the first line ```javascript var message = "hello" + " and welcome"; ``` ## Node ### Require - Use uppercase variable names for imported modules - All require statements must be declared at the top of the module - Always use relative paths ### Module globals - Every module can only have two top level globals: - `exports` - defined automatically by node - `internals` - must be declared as an object at the top of each module immediate following the `require` section - Any variable global to the module must be a property of `internals`, including constants - If a module has automatically executing code, it must be contained within a function (using the `internals` namespace) and called at the top of the module after the `internals` declaration ### Variable names - `err` is reserved for errors received via a callback. Use `error` for local function variables. ### Callback - First argument must always be `err` - If a function takes a `callback` argument, it **must** be called on `process.nextTick()`. Otherwise, the argument name **must** be `next` to clearly declare that it may get called on same tick.