Skip to content

Instantly share code, notes, and snippets.

@young-steveo
Last active December 21, 2015 07:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save young-steveo/6271942 to your computer and use it in GitHub Desktop.
Save young-steveo/6271942 to your computer and use it in GitHub Desktop.
Zumba Javascript Code Standard for internal and third-party use

Zumba Javascript Code Standard

Contents

  1. Preface
  2. Quick Reference
  3. General Naming
  4. Specific Naming
  5. Layout
  6. Variables
  7. Objects & Arrays
  8. Functions & Scope
  9. Documentation
  10. Backbone.js
  11. Require.js
  12. Files

Preface

Any violation of this standard is allowed if it enhances readability or circumvents a considerable performance issue. Make sure to clearly document the differences between the standard and the code as written.

Quick Reference

Core Naming Constructs

Construct Convention Example
constant UPPER_CASE Speeds.ANIMATION_SPEED
constructor CamelCase ShoppingCartView
public method mixedCase lib.doSomething()
public var mixedCase var firstName;

General Naming

Constructors

  1. Constructors should be nouns
  2. Constructors should be named using CamelCase capitalization:
var Product = function(){};

Constants

Constants should be placed in a frozen object created as a container for constants, emulating an Enum:

  1. The enum container should be named using CamelCase capitalization.
  2. The keys should be named with UPPER_CASE capitalization.
  3. The constant container should be declaired in the smallest scope possible.
var AnimationSpeeds = Object.freeze({
    VERY_SLOW : 2000,
    FAST : 700,
    VERY_FAST : 100
});

Visibility

Avoid prefixing private methods or properties with a _ (underscore) character. Code should be refactored to encapsulate private members and prevent them from being exposed. Private members follow the same naming conventions as public members.

// using require.js
define(function(){
    var PublicThing, privateMethod;
    
    PublicThing = function(){};
    PublicThing.prototype.doSomething = function(){
        return privateMethod.call(this);
    };
    
    privateMethod = function(){ // NOT _privateMethod
        // ...
    };
    
    return PublicThing;
});

Clarity

All names should be written in English.

Names should be as clear as necessary and should avoid unclear shortenings and contractions

var ZumbiniClass; // NOT ZbiniClass
var mouseEventHandler; // NOT mseEvtHdlr

If context can be determined by module/library membership, this context should be used to determine if a member name is clear:

events.Mouse.handler // NOT events.Mouse.mouseEventHandler

Hungarian Notation

Always avoid Hungarian Notation in favor of semantic naming

// incorrect
var Hungarian = function(){
     // local variable prefixed with $ to indicate a jQuery object
    var $this = $(this);
    
     // property prefixed with it's datatype
    this.arrThings = [];
    
     // property prefixed with $ to indicate a jQuery object
    this.$elements = $('.elements');
};

// correct
var MuchBetter = function(){
    var instance = $(this);
    
    this.things = [];
    this.elements = $('.elements');
};

Misc.

Abbreviations and acronyms should not be UPPERCASE when used as a name:

getHtml(); // NOT getHTML()
JsonView;  // NOT JSONView

Names that are methods should be verbs or verb phrases written with mixedCase in the verbSubject format:

lib.doSomething();
lib.get('something');
lib.handleJsonData();

Specific Naming

  1. Boolean variables, properties and methods should be prefexed with is, has, can or should, i.e. lib.isAnimating(), lib.canAnimate.
  2. Collections must be plural: var things = [];
  3. Variables representing a number of objects should be named length, or alternatively include a num prefix or Count suffix: var length, numEvents, productCount;
  4. Iterator variables should be named i, j, k, etc.
  5. Avoid negated/inverted boolean names: isNotError, isNotFound are unacceptable.
  6. Methods that return void should be named after what they do, methods that return an Object should be named after what they return.

Layout

Line Length

  1. Try to keep lines shorter than 80 characters, and AVOID lines longer than 100 characters. When a statement will not fit on a single line, break it.
  2. When breaking a line to reduce line length, place the break after an operator, ideally after a comma.

Block Statements

Block layout should be like so:

while (!isDone) {
    doSomething();
    isDone = moreToDo();
}

if statements should have the following form:

if (condition) {
    statements;
} else if (anotherCondition) {
    statements;
} else {
    statements;
}

for statements should have the following form:

var i; // predefined
for (i; condition; update) {
    statements;
}

while statements should have the following form:

while (condition) {
    statements;
}

do ... while statements should have the following form:

do {
    statements;
} while (condition);

switch statements should have the following form:

switch (condition) {
    case ABC:
        statements;
        // fallthrough
    case DEF:
        statements;
        break;
    default:
        statements;
        // no break on the last case -- it's redundant
}

A single statement if else, while or for block must not be written without brackets, but CAN be written on the same line if the line length does not become excessive:

if (condition) { statement; }
while (condition) { statement; }
for (i; condition; update) { statement; }

Whitespace, Commas & Semicolons

Code should never rely on Automatic Semicolon Insertion.

Comma seperators, when combined with line breaks, should be used to terminate a line, not start a line:

var correct = {
    key1 : 'value', // correct
    key2 : 'value'
};

var incorrect = {
    key1 : 'value'
  , key2 : 'value' // NOT correct
};

Trailing whitespace should be trimmed.

Logical units within a block should be seperated by one blank line:

var doThings = function(obj){
    var formattedObject; // space following declaration
    
    formattedObject = getFormattedObject(obj);
    formattedObject.moreStuff = true; // space following logical unit
    
    processObject(formattedObject);
};

Whitespace may be used for alignment to enhance readability.

Comments

  1. Tricky or overly complex code should not be commented. It should be rewritten.
  2. Comments should be written in English.
  3. Comments should be indented relative to their position in the code.
  4. Comments should not be included for every single line of code.

Variables

Variables should be initialized at the top of the smallest scope possible.

Variables can be declared and assigned a value simultaneously, but only if all variables in the var statement are treated equally:

var things, moreThings; // correct

var things = [], moreThings = []; // correct

var things = [], moreThings; // NOT correct

Conditions

Use temporary boolean variables in lieu of complex conditional expressions.

Always test for truth in the if part of an if else expression:

if (isAcceptable){ // correct
    nominalStatements;
} else {
    exceptionalStatements;
}

if (!isAcceptable){ // incorrect
    exceptionalStatements;
} else {
    nominalStatements;
}

if (!isAcceptable){ // correct, since there is no `else`
    
}

Objects & Arrays

Literals

  1. Always use {} instead of new Object().
  2. Always use [] instead of new Array().

Object properties

When possible, use dot notation instead of array notation when accessing an object property:

obj['someKey']; // Array notation
obj.someKey; // Use this instead

The JSON spec enforces quotation marks around object property keys. However, avoid using quoted keys in object literals when possible. Refactor dashes and illegal characters whenever possible to uphold this guideline:

// incorrect
var bad = {
    "normalKey" : false,
    "dash-key" : false,
    "space key" : false
};

// correct
var good = {
    normalKey : true,
    dashKey : true,
    spaceKey : true
};

Rules of Thumb

If possible, try not to mix types in an array:

// bad
var things = [1, "stuff", true];

// good
var things = {
    quantity : 1,
    name : "stuff",
    active : true
};

Remember that Objects and Arrays are assigned/passed by reference, and watch out for gotchas:

// these two variables now point to the same object
var someThings = otherThings = {};

someThings.same = true;

console.log(otherThings.same); // reports true

Functions & Scope

Documentation

Constructors, their members, and private methods/variables should be preceeded by a docblock as follows:

define(function(){
    var Jedi, Alignments, forceLevel, useTheForce;
    
    /**
     * Various Force Alignments
     * 
     * @type Object
     */
    Alignments = Object.freeze({
        DARK_SIDE : 0,
        LIGHT_SIDE : 1
    });
     
    /**
     * A private variable, global to the Jedi object
     * 
     * @type Number
     */
    forceLevel = 100;
    
    /**
     * Jedi object
     * 
     * A short description of Jedi
     * 
     * @constructor
     * @param ConstructorName injectedObject
     */
    var Jedi = function(injectedObject){
        statements;
    };
    
    /**
     * A Static method (notice the lack of `prototype` in the definition)
     * 
     * @param Number level
     * @return void
     * @static
     */
    Jedi.setForceLevel = function(level){
        forceLevel = level;
    };
    
    /**
     * Describing the mindTrick method
     * 
     * @param String target
     * @return void
     */
    Jedi.prototype.mindTrick = function(target){
        useTheForce.call(this, target);
    };
    
    /**
     * A private method
     * 
     * @param String target
     * @return void
     */
    useTheForce = function(target){
        statements;
    };
    
    return Jedi;
});

It is important that comments are kept current. Out-dated comments can make the code hard to read and understand.

Comments should focus on what is not immediately visible. Don't waste time with useless comments like the following:

 var i = 0; // Set i to zero.

Backbone.js

Require.js

Files

Avoid in-line javascript.

Logical units (e.g. Modules, Constructors, Libraries, Configuration, Templates, etc.) should always be seperated into individual files containing a single unit.

Configuration files should favor the JSON format and use the .json extension

Folder Structure

/js
    /config # JSON files
    /libs   # First party libraries
    /models # Backbone.js models
    /vendor # Third party libraries
    /views  # Backbone.js views
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment