This style guide includes recommended practices for consistency. If any of the rules conflicts with readability in a particular case, ignore the rules and chose readability.
Set your editor to use below settings. Optionally use http://EditorConfig.org.
- Character set
UTF-8
- Indent: 4 spaces (there should be no tabs in the codebase)
- Line ending:
LF
(Unix-style) - Trim trailing whitespace
- Max line length: keep it reasonable
Not settable by EditorConfig:
- Function declaration
- Anonymous:
function () {}
, notfunction() {}
- Named:
function foo() {}
, notfunction foo () {}
- Anonymous:
- Function invocation
func(arg)
, notfunc (arg)
- No leading or trailing spaces, for example,
(arg)
not( arg )
- Space after
,
&;
unless end of line. For example:[1, 2, 3, 4, 5, 6]
for (i = 0; i < length; i++)
1 + 1
, not1+1
- Space before & after comment blocks
// comment
not//comment
/* comment */
not/*comment*/
- Serialization bracing in HTML template, as generated by minit:
<script type="text/montage-serialization">
{
"owner": {
"properties": {
"element": {"#": "main"}
}
}
}
</script>
- 50/72 style, more @ http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html, for example,:
50 1st line, 1st word capitalized, no period
(blank line)
72 3rd & following lines
- Use imperative verbs - "add", not "adds" / "added" / "adding"
General
- Do not abbreviate unless if it's a well known term, for example, abbreviate
min
,max
,config
, don't abbreviateEarthquakeOverlay
intoEQOverlay
JavaScript
- Components & prototypes - must be upper CamelCase, for example,
ComponentFoo
; prototype name in serialization block auto converted to such case - Boolean flags - prefix with
is
orhas
, for example,isFoo
- Private variable name - prefix with
_
, for example,_foo
- Constant variable name -
EMPTY_ARRAY
- Prefer
self
overthat
orme
, etc., for example,var self = this;
CSS
- For components in Montage Framework & associated UI sets, always prefix with a namespace. For example,
.montage-ComponentFoo
,.digit-ComponentFoo
. - For apps using Montage Framework, we also recommend to optionally prefix with app name to distinguish source of components. For example,
.myApp-ComponentFoo
.
Files & Directories
component-foo.reel
TODO: to be merged in: https://github.com/montagejs/montage/wiki/Naming-Conventions
Order
- Prefer alphabetical ordering, unless the natural order of a sequence would be immediately obvious to anyone reading the code. For
require
s,switch
cases, etc.
- Terminate statements with
;
- Declare variables at top of block
- Declare multiple variables with single
var
statement & commas; can do in 1 line if not many variables - Define constructor function at top of block
- Use K&R style braces,
{
at end of line, for example,:
return {
status: 'ok'
};
- No braces for 1-line
if
statements - Prefer
===
and!==
unless need==
or!=
behaviour strict
mode - TBD- Multiline string
var longString = 'A rather long string of English text, an error message ' +
'actually that just keeps going and going';
- Getters before setters
- Indent method chains, for example:
loadFile
.then()
.then()
.catch()
Error handling
TBD
Performance
- Async - prefer callback over promises in implementation, where performance matters; prefer promises in MontageJS APIs
- Prefer
for
ordo
-while
loops overforEach
- Avoid closures
QA
- Hinting - TBD
- Testing - Jasmine + montage-testing
- Write in JSDoc + markdown
- Prefer standard tags over synonyms, for example,
@function
, not@func
or@method
- Prefer
.prototype
over#
due to lack of JSDoc documentation on#
and lack of support for it in certain editors, such as WebStorm
Comment style
/**
* @private
* @property {Object[]} value
*/
// not
/**
@private
@property {Object[]} value
*/
Getter / setters
If setting a private variable, document everything on getter / setter; if not, document on private variable.
/**
* Description
*
* @property {PressComposer} value
* @default null
* @private
*/
_pressComposer: {
value: null
},
/**
* @private
*/
_active: {
value: false
},
/**
* Description
*
* @property {boolean}
* @default false
*/
active: {
get: function () {
return this._active;
},
set: function (value) {
this._active = value;
this.needsDraw = true;
}
},
I am not a big fan of the one-line if without braces. It's a statements block (even if it's a very short one) and as such, I would expect it to be written as all others blocks (as JSHint does).
Regarding the header block comments, could we leave ascii art where it belongs (in the 90's...) ? 😃
Last point, the anonymous functions declarations. I can live with a space before the opening parenthesis (even if I generally avoid it, I'll configure my editor to do that for me), but what about going one step further and promoting named closures. It makes the developer give clues about its intentions in the function and helps debugging (no more "in Anonymous function" lines in stacktraces). Of course, that should be a loose rule (for map or filter parameters, by example).