Skip to content
This repository has been archived by the owner on May 14, 2022. It is now read-only.

Latest commit

 

History

History
492 lines (388 loc) · 12.1 KB

code-standard.md

File metadata and controls

492 lines (388 loc) · 12.1 KB

Cheat Sheet Code Standard

Table of Contents

Javascript

Naming

  • 1.1 camelCase & descriptive:
    • Camel case for variables and functions
    • Describe what the variable store or function does
    // bad
    const Variable
    const variable_one
    const dE
    const date  //not descriptive
    
    // good 
    const dateExpired
    function checkDateExpired() {}

  • 1.2 UpperCamelCase:
    • Upper camel case for clases
     // bad
     class session {}
     class session_user {}
     class sessionUser {}
    
     // good 
     class Session {}
     class SessionUser {}

  • 1.3 dash-case:
    • Dash case for files
     # bad
     SessionUser.js
     Session_User.js
     session_user.js
    
     # good 
     session-user.js

  • 1.4 Avoid: [1]
    • Do not use trailing or leading underscores

    Why? JavaScript does not have the concept of privacy in terms of properties or methods. Although a leading underscore is a common convention to mean “private”, in fact, these properties are fully public, and as such, are part of your public API contract. This convention might lead developers to wrongly think that a change won’t count as breaking, or that tests aren’t needed. tl;dr: if you want something to be “private”, it must not be observably present.

     // bad
     this.__firstName__ = 'Panda';
     this.firstName_ = 'Panda';
     this._firstName = 'Panda';
    
     // good
     this.firstName = 'Panda';

Variables

  • 2.1 Declaration:
    • use const for value that not change and let to others
    • Always use const or let to declare variables. Not doing so will result in global variables.[1]
    // bad 
    globalVariable = true 
    
    const globalVariable = true;
    globalVariable = false;
    
    // good 
    const scopeVarible = true ;
    
    let globalVariable = true;
    globalVariable = false;

  • 2.2 Caching Values:
    • cache the lookup once
    //bad
    if( orders[index].state == '' || orders[index].state == 'EMPTY'){
    }
    
    if( order.state == '' || order.state == 'EMPTY' || order.state == 'OPEN'){
    }
    
    //good 
    const orderState = orders[index].state;
    
    if( orderState == '' || orderState == 'EMPTY'){
    }

  • 2.3 Grouping Declarations:
    • Group all your consts and then group all your lets [1]
    // bad
    let i;
    const items = getItems();
    let dragonball;
    const goSportsTeam = true;
    let len;
    
    // good
    const goSportsTeam = true;
    const items = getItems();
    let dragonball;
    let ordersIndex;
    let ordersLength;

Typings (for project with Typescript)

TBD - use types of Node.js or interfaces, avoid any always

Classes

TBD - no constructor no public accesor explicit

Objects

TBD - immutable as much as posible ; use map, filter ...

Basic Types(Declarations)

  • TypeScript support different types of data types
    // bad
    Boolean
    var isEmtpy = false;
    function receiveResponse (response) {
        isEmpty = response;
    }
    
    Number
    var myNumber = 17;
    myNumber;
    
    String
    var myColor = "black";
    myColor = "";
    
    Array 
    var arr = [];
    arr = [12];
    
    Methods
    function myMethod(s);
    function handlerEvent (event) {
        let mouseEvent = event as MouseEvent;
    }
    
    Interface
    var foo = {};
    foo.bar = 123; // Error: property 'bar' does not exist on `{}`
    foo.bas = 'hello';
    
    // good
    Boolean
    let isResponse: boolean = false;
    function receiveResponse (response: boolean) {
        isResponse = response;
    }
    Number
    let myNumber: number = 17;
    
    String
    let myColor: string = "black";
    myColor = 'red';
    
    Array
    let arrNumber: Array<number> = [];
    let arrString: Array<string> = [];
    
    Methods
    function myMethod(s: string): string;
    function handlerEvent (event: Event) {
        const mouseEvent = event as MouseEvent;
    }
    
    Interface
    interface Foo {
        bar: number;
        bas: string;
    }
    const foo = {} as Foo;
    foo.bar = 123;
    foo.bas = 'hello';
    
    Any
    let notSure: any = 4;
    notSure = "maybe a string instead of number";

Code Structure

  • 6.1 Don’t chain variable assignments [1]

    Why? Chaining variable assignments creates implicit global variables.

    // bad
    (function example() {
    // JavaScript interprets this as
    // let a = ( b = ( c = 1 ) );
    // The let keyword only applies to variable a; variables b and c become
    // global variables.
    let a = b = c = 1;
    }());
    
    console.log(a); // throws ReferenceError
    console.log(b); // 1
    console.log(c); // 1
    
    // good
    (function example() {
    let a = 1;
    let b = a;
    let c = a;
    }());
    
    console.log(a); // throws ReferenceError
    console.log(b); // throws ReferenceError
    console.log(c); // throws ReferenceError
    
    // the same applies for `const` 

  • 6.2 Ternaries should not be nested and generally be single line expressions. [1]
    // bad
    const foo = maybe1 > maybe2
    ? "bar"
    : value1 > value2 ? "baz" : null;
    
    // split into 2 separated ternary expressions
    const maybeNull = value1 > value2 ? 'baz' : null;
    
    // better
    const foo = maybe1 > maybe2
    ? 'bar'
    : maybeNull;
    
    // best
    const foo = maybe1 > maybe2 ? 'bar' : maybeNull;

  • 6.3 When mixing operators, enclose them in parentheses. The only exception is the standard arithmetic operators (+, -, *, & /) since their precedence is broadly understood. eslint: no-mixed-operators [1]

    Why? This improves readability and clarifies the developer’s intention.

    // bad
    const foo = a && b < 0 || c > 0 || d + 1 === 0;
    
    // bad
    const bar = a ** b - 5 % d;
    
    // bad
    // one may be confused into thinking (a || b) && c
    if (a || b && c) {
    return d;
    }
    
    // good
    const foo = (a && b < 0) || c > 0 || (d + 1 === 0);
    
    // good
    const bar = (a ** b) - (5 % d);
    
    // good
    if (a || (b && c)) {
    return d;
    }
    
    // good
    const bar = a + b / c * d;

Casting & Coercion

  • 7.1 Strings: [1]

    // => this.reviewScore = 9;
    
    // bad
    const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"
    
    // bad
    const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf()
    
    // bad
    const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string
    
    // good
    const totalScore = String(this.reviewScore);

  • 7.2 Numbers: Use Number for type casting and parseInt always with a radix for parsing strings. [1]

    const inputValue = '4';
    
    // bad
    const val = new Number(inputValue);
    
    // bad
    const val = +inputValue;
    
    // bad
    const val = inputValue >> 0;
    
    // good but it's better specify decimal
    const val = parseInt(inputValue);
    
    // good
    const val = parseInt(inputValue, 10);
    
    // good
    const val = Number(inputValue);

  • 7.3 Booleans: [1]

    const age = 0;
    
    // bad
    const hasAge = new Boolean(age);
    
    // good
    const hasAge = Boolean(age);
    
    // best
    const hasAge = !!age;

Comments

[1]

  • 8.1 Use /** ... */ for multi-line comments.

    // bad
    // make() returns a new element
    // based on the passed in tag name
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {
    
      // ...
    
      return element;
    }
    
    // good
    /**
     * make() returns a new element
     * based on the passed-in tag name
     */
    function make(tag) {
    
      // ...
    
      return element;
    }

  • 8.2 Use // for single line comments. Place single line comments on a newline above the subject of the comment.

    // bad
    const active = true;  // is current tab
    
    // good
    // is current tab
    const active = true;
    
    // good
    function getType() {
      console.log('fetching type...');
    
      // set the default type to 'no type'
      const type = this.type || 'no type';
    
      return type;
    }
    
    // also good
    function getType() {
      // set the default type to 'no type'
      const type = this.type || 'no type';
    
      return type;
    }

  • 8.3 Prefixing your comments with FIXME or TODO helps other developers quickly understand if you’re pointing out a problem that needs to be revisited, or if you’re suggesting a solution to the problem that needs to be implemented. These are different than regular comments because they are actionable. The actions are FIXME: -- need to figure this out or TODO: -- need to implement.

  • 8.4 Use // FIXME: to annotate problems.

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // FIXME: shouldn’t use a global here
        total = 0;
      }
    }

  • 8.5 Use // TODO: to annotate solutions to problems.

    class Calculator extends Abacus {
      constructor() {
        super();
    
        // TODO: total should be configurable by an options param
        this.total = 0;
      }
    }

Avoid

Never evaluate a string

// bad 
eval(new String("2 + 2")); 
eval("2 + 2");

new Function("x", "y", "return x * y");

[1] Getting from AirBnB style guide

Versioning

Pull Request