hapi
Version:
HTTP Server framework
679 lines (489 loc) • 13.8 kB
Markdown
# 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.