Skip to content

Latest commit

 

History

History
681 lines (511 loc) · 14.5 KB

code-style-guide.md

File metadata and controls

681 lines (511 loc) · 14.5 KB

Catberry Code Style Guide

There are some aspects of Catberry code style below:

Table Of Contents

  1. Formatting
  2. JavaScript
  3. Naming
  4. Variables
  5. Objects
  6. Arrays
  7. Types
  8. Functions
  9. Strings
  10. Blocks
  11. Comments
  12. Code Quality Tools

Formatting

  • Always use tabs (hard tabs)

  • Never leave trailing whitespaces

  • Never use multiple line breaks

  • Maximum length of line — 80

  • Always use semicolons

  • Always use a space after keywords and before curly braces

     // bad
     if(some){
     
     }else{
     	
     }
     
     // good
     if (some) {
     
     } else {
     
     }
  • Set off operators with spaces.

     // bad
     var x=y+5;
     
     // good
     var x = y + 5;
  • Use indentation when making long method chains.

     // bad
     $('#items').find('.selected').highlight().end().find('.open').updateCount();
     
     // good
     $('#items')
     	.find('.selected')
     	.highlight()
     	.end()
     	.find('.open')
     	.updateCount();
  • Never use leading commas

     // bad
     var once
     	, upon
     	, aTime;
     
     // good
     var once,
     	upon,
     	aTime;
  • Always use curly braces where it's possible, the first brace on same line and space before it

     // bad
     if (condition)
     {
     }
     if(condition2){
     }
     
     // good
     if (condition) {
     
     }

⬆ back to top

JavaScript

⬆ back to top

Naming

  • Always use camelCase for variables, PascalCase for constructors and UPPER_CASE with underscores for constants

     var SOME_CONSTANT = 42;
     
     function Constructor() {
     	var someVariable = 'someValue';
     }
  • Avoid single letter names. Be descriptive with your naming.

     // bad
     function q() {
     	// ...stuff...
     }
     
     // good
     function query() {
     	// ..stuff..
     }
  • Use a leading underscore _ when naming private properties

     // bad
     this.__firstName__ = 'Panda';
     this.firstName_ = 'Panda';
     
     // good
     this._firstName = 'Panda';
  • When saving a reference to this use name self.

     // bad
     	function() {
     		var _this = this;
     		return function() {
     			console.log(_this);
     		};
     	}
     // good
     function() {
     	var self = this;
     	return function() {
     		console.log(self);
     	};
     }
  • If the variable is boolean type then start its name with is or has prefix

     // bad
     var success = true;
     
     // good
     var isSuccess = true;
  • If JavaScript file has definition of a constructor it should have a name of this constructor in PascalCase like Constructor.js

⬆ back to top

Variables

  • Always use var to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace.

     // bad
     superPower = new SuperPower();
     
     // good
     var superPower = new SuperPower();
  • Use one var declaration for multiple variables and declare each variable on a newline.

     // bad
     var items = getItems();
     var goSportsTeam = true;
     var dragonBall = 'z';
     
     // good
     var items = getItems(),
     	goSportsTeam = true,
     	dragonBall = 'z';
  • Declare unassigned variables last. This is helpful when later on you might need to assign a variable depending on one of the previously assigned variables.

     // bad
     var i, len, dragonBall,
     	items = getItems(),
     	goSportsTeam = true;
     
     // bad
     var i, items = getItems(),
     	dragonBall,
     	goSportsTeam = true,
     	len;
     
     // good
     var items = getItems(),
     	goSportsTeam = true,
     	dragonBall,
     	length,
     	i;
  • Assign variables at the top of their scope. This helps avoid issues with variable declaration and assignment hoisting related issues.

     // bad
     function () {
     	test();
     	console.log('doing stuff..');
     
     	//..other stuff..
     
     	var name = getName();
     
     	if (name === 'test') {
     		return false;
     	}
     
     	return name;
     }
     
     // good
     function () {
     	var name = getName();
     
     	test();
     	console.log('doing stuff..');
     
     	//..other stuff..
     
     	if (name === 'test') {
     		return false;
     	}
     	
     	return name;
     }
     
     // bad
     function () {
     	var name = getName();
     	
     	if (!arguments.length) {
     		return false;
     	}
     	
     	return true;
     }
     
     // good
     function () {
     	if (!arguments.length) {
     		return false;
     	}
     	
     	var name = getName();
     	
     	return true;
     }

⬆ back to top

Objects

  • Always use the literal syntax for object creation.

     // bad
     var item = new Object();
     
     // good
     var item = {};
  • When possible do not use delete operator. In some, cases it can cause performance degradation.

  • Use dot notation when accessing properties.

     var luke = {
     	jedi: true,
     	age: 28
     };
     
     // bad
     var isJedi = luke['jedi'];
     
     // good
     var isJedi = luke.jedi;
  • Use subscript notation [] when accessing properties with a variable.

     var luke = {
     	jedi: true,
     	age: 28
     };
     
     function getProp(prop) {
     	return luke[prop];
     }
     
     var isJedi = getProp('jedi');

⬆ back to top

Arrays

  • Always use the literal syntax for array creation.

     // bad
     var array = new Array();
     
     // good
     var array = [];
  • Edit array items only using:

  • push

  • pop

  • shift

  • unshift

  • slice

  • splice

var array = [1, 2, 3]; 

// bad
array[array.length] = 'some';

// good
array.push('some');
var array = [1, 2, 3, 4, 5];

// bad
var hasGreaterThanThree = false;
for (var i = 0; i < array.length; i++) {
	if (array[i] > 3) {
		hasGreaterThanThree = true;
		break;
	}
}

// good
var hasGreaterThanThree = array.some(function (item) {
	return item > 3;
});
  • To convert an array-like object to an array, use the slice like this

     var args = Array.prototype.slice.call(arguments);
  • When you need to copy an array use slice like this

     var items = [1, 2, 3, 4, 5],
     	itemsCopy = items.slice();

⬆ back to top

Types

  • Always use explicit type conversion with Number, Boolean and String (.toString()) functions

     // bad
     var boolean = !!some,
     	number = +some,
     	string = '' + some,
     	hasDot = ~string.indexOf('.');
     
     // good
     var boolean = Boolean(some),
     	number = Number(some),
     	string = String(some),
     	string = some.toString(),
     	hasDot = string.indexOf('.') !== -1;
  • Use only ===(!==) operator

⬆ back to top

Functions

  • Function expressions:

     // anonymous function expression
     var anonymous = function () {
     	return true;
     };
    
     // named function expression
     var named = function named() {
     	return true;
     };
    
     // immediately-invoked function expression (IIFE)
     (function () {
     	console.log('Welcome to the Internet. Please follow me.');
     })();
  • Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead. Browsers will allow you to do it, but they all interpret it differently.

    Note: ECMA-262 defines a block as a list of statements. A function declaration is not a statement. Read ECMA-262's note on this issue.

     // bad
     if (currentUser) {
     	function test() {
     		console.log('Nope.');
     	}
     }
     
     // good
     var test;
     if (currentUser) {
     	test = function test() {
     		console.log('Yup.');
     	};
     }
  • Never name a parameter arguments, this will take precedence over the arguments object that is given to every function scope.

     // bad
     function nope(name, options, arguments) {
     	// ...stuff...
     }
     
     // good
     function yup(name, options, args) {
     	// ...stuff...
     }
  • Never use constructor functions for side-effects

     // bad
      new Constructor();
     
     // good
     var variable = new Constructor();
  • Always chain function calls when possible

     // bad
     var mapped = array.map(mapper),
     	filtered = mapped.filter(filter);
     
     filtered.forEach(handler);
     
     // good
     array
     	.map(mapper)
     	.filter(filter)
     	.forEach(handler);
  • Separate function arguments with the space after a comma

     // bad
     function some(first,second,third) {
     
     }
     
     // good
     function some(first, second, third) {
     
     }
  • Use constructor and prototype to define a module when you need to store local state like this:

     
     'use strict';
     
     var MILE_MULTIPLIER = 0.6214;
     
     /**
      * Creates a new instance of distance descriptor.
      * @constructor
      */
     function DistanceDescriptor() {
     	// here could be some initialization
     }
     
     DistanceDescriptor.prototype._distance = 0;
     
     /**
      * Sets distance in miles.
      * @param {Number} distance Distance in miles.
      */
     DistanceDescriptor.prototype.setDistanceInMiles = function (distance) {
     	this._distance = distance / MILE_MULTIPLIER;
     };
     
     /**
      * Sets distance in kilometers.
      * @param {Number} distance Distance in kilometers.
      */
     DistanceDescriptor.prototype.setDistanceInKilometers = function (distance) {
     	this._distance = distance;
     };
     
     /**
      * Gets distance in miles.
      */
     DistanceDescriptor.prototype.getDistanceInMiles = function () {
     	return this._distance * MILE_MULTIPLIER;
     };
     
     /**
      * Gets distance in kilometers.
      */
     DistanceDescriptor.prototype.getDistanceInKilometers = function () {
     	return this._distance;
     };
     
  • Use bind for partial application or to specify this inside the method.

⬆ back to top

Strings

  • Use only single quotes for strings

     // bad
     var string = "very bad string";
     
     // good
     var string = 'this is a good one';
  • Strings longer than 80 characters should be written across multiple lines using string concatenation like this:

     // bad
     var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
     
     // bad
     var errorMessage = 'This is a super long error that was thrown because \
     	of Batman. When you stop to think about how Batman had anything to do \
     	with this, you would get nowhere \
     	fast.';
     
     // good
     var errorMessage = 'This is a super long error that was thrown because ' +
     	'of Batman. When you stop to think about how Batman had anything to do ' +
     	'with this, you would get nowhere fast.';

⬆ back to top

Comments

  • Always use jsDoc for everything

  • Use one line comments // instead /* ... */

     // bad
     
     /*
      Some 
      multiline 
      comment
     */
     
     // good
     
     // Some
     // multiline
     // comment
  • Use // TODO: to annotate solutions or problems

     function Calculator() {
     	// TODO: total should be configurable by an options param
     	this.total = 0;
    
     	return this;
     }

⬆ back to top

Code Quality Tools

Code style should be checked by:

These tools should be called before tests by command npm test.

⬆ back to top