/dig-deep

Group entry to 2015 EMU hackathon. Small 3D dungeon crawler type game made with three.js

Primary LanguageJavaScript

dig-deep

Group entry to the 2015 EMU hackathon. Small 3D dungeon crawler type game made with three.js

What is this?

This document will serve as both a JavaScript style guide, and eventually a design document for Dig Deep. What follows is the style guide. Further documentation pending.

The purpose of this guide is to provide a set of standards for the writing and design of this project. Implementation of this guide will provide uniformity in code style and formatting in order to improve the quality of the code we are writing, making it consistent, readable, and maintainable. Ultimately code should appear as if it were written by one person. It should be easy for any third party to understand, use, and contribute to your code. Violations to this guide are allowed if they enhance readability.

Inspiration for this guide was taken from similar style guides such as those by idiomatic, airbnb, jQuery, Google, Aloha, Dojo and other sources around the web. This document, like anything I make, is mostly an amalgamation of other people's wonderful ideas wrapped up in one place for my purposes. If you see any problems with it, or think you could improve it, feel free to modify this document and submit a pull request.

A certain amount of familiarity with the JavaScript language and programming in general, as well as with the project at hand, will be assumed throughout.

Table of Contents

  1. Foreward
  2. Conventions - Linting
  3. Choices - Indentation - Quotation
  4. Naming - CSS
  5. Declarations - Literals
  6. Formatting - Whitespace - Commas - Semicolons
  7. Comments
  8. Further

Conventions

  • 1.1 This project is being written in JavaScript. Despite the availability of compile to js languages, all efforts should be made to keep our codebase purely in JavaScript.

  • 1.2 In keeping with this, we should also minimize our use of external libraries. This is for the sake of simplicity in reasoning about the code, as well as forcing us to actually know what we're doing and reducing the number of bugs caused by third-party code. The majority of our code should be written by us.

  • 1.3 Write with the intent of producing readable code. Expect that someone else will have to read and understand your code at some point. Use the correct whitespace and formatting to ensure readabililty. Finished code will be minified, so just write nicely.

  • 1.4 If it wasn't already obvious from the webpage you're likely viewing this from, our projects will be managed through github. If you aren't familiar with github, here's a quick primer. You should have a basic understanding of git, it's simple and useful.

  • 1.5 Use JSHint for linting. Linting helps to detect and fix errors, and is considered good practice.

Choices

Much like the oxford comma, there are many things within JavaScript that are simply a matter of preference. Some of these choices were made entirely arbitrarily and with no meaning. These are things that are entirely at the discretion of the project authors. JavaScript handles them exactly the same way internally. The only thing that is important, is consistency. Pick one and stick to it for the entire project. For your consideration:

  • 2.1 Whether you indent by tabs or spaces. And, if you should choose spaces, whether you indent by 2 or 4 spaces. Crockford and others argue against the use of tabs for indentation, as there is no standard way of handling tabstops. Indenting by spaces can increase whitespace and filesize in a large project, but this is mitigated in the minification process.

This project will opt for the use of 2 spaces as indentation.

  • 2.2 Whether you use single or double quotations. If double quotations are used, single quotes are allowed for inner quotes.

After a thoughtful discussion, the main collaborators for this project have settled on the single quote style.

Naming

  • 3.1 Names should be written in short, simple, descriptive English.

  • 3.2 Names should be easy to understand. Favor naming to functionality over values.

  • 3.3 Avoid names that are misleading, or have multiple meanings.

  • 3.4 Don't obfuscate names, for example by removing all vowels. Understandable abbreviations are acceptable, but in general should be avoided. The main point is to keep it humanly readable.

  • 3.5 Avoid magic numbers, use named constants. Program for the future. Constants should be named in all caps, with underscores used to separate words.

SOME_CONSTANT
  • 3.6 Use CamelCase for class names and mixedCase for method and property names.

  • 3.7 Don't use the underscore character, except as noted in 3.5 and 3.9.

//bad
unitPos_X

//good
unitPositionX
  • 3.8 Method names should be verbs.

  • 3.9 Methods and properties that are determined to be private should be prepended with an underscore (_)

  • 3.10 Use is or has/can/should for boolean variables and methods. Avoid negated booleans.

//bad
isNotThing

//good
isThing
  • 3.11 Use compute when naming functions that perform computations.

  • 3.12 Use find when naming functions that looks up some value.

  • 3.13 Methods may be named after what they return. If the return void instead of an object then after what they do.

  • 3.14 Collections should be plural.

  • 3.15 Iterators should be named i, j, k, etc. They should be defined in the loop constructor. It's significantly more readable than anticipating variable hoisting.

  • 3.16 Avoid checking for array length in every iteration of a loop. Set another variable to hold the length in the loop constructor.

var names = ['George', 'Ringo', 'Paul', 'John'];
for(var i = 0, j = names.length; i < j; i++) {
	doSomeThingWith(names[i]);
}
  • 3.17 Generic variables should have the same name as their type.
//where topic is of type Topic
setTopic(topic)
  • 3.18 Initialization methods should be named init().
//good
init()
initSidebar()

//bad
initialize()
initializeSomething()
start()
run()
  • 3.19 Don’t use “that” to refer to an outer “this”. Use the name of the class instead (with first char lowercased).
var MyObject = Class.extend({
    _constructor: function() {
        // GOOD
        var myObject = this;
        setTimeout(function() {
            console.log(myObject.name + ' done.');
        };
 
        // BAD
        var that = this;
        setTimeout(function() {
            console.log(that.name + ' done.');
        };
    }
});
  • ###CSS CSS files follow basically the same set of conventions as javascript.
    • Each selector is on a new line
    • The opening curly brace is preceded by a space
    • The key value pairs have a space after the colon
    • Every block is followed by an empty new line
.className {
  color: red;
}

.className,
#anId {
  color: blue;
}

Declarations

  • 4.1 Use literal syntax for objects and arrays
//bad
var squid = new Object();
var reefs = new Array();

//good
var squid = {};
var reefs = [];
  • 4.2 Initialize variables where they're declared, even if it's a null declaration.
var someObject = {};

Formatting

  • 5.1 ALWAYS use brackets and semicolons where applicable.

  • 5.2 Related variables of the same type should be declared in a common statement. Unrelated variables or those of different type must have a separate var declaration.

  • 5.3 Floating point constants should always be named with at least one number before and after the decimal point.

var position.x = 0.0;
  • 5.4 An effort should be made to contain scope for the purpose of keeping variables alive for the smallest amount of time possible.

  • 5.5 Commas should be followed by a space or newline.

  • 5.6 No preceding space on commas or semicolons.

  • 5.7 No whitespace at eol or on blank lines.

//this is important
  • 5.8 Unary operators(!, ++) should not have a space next to their operator.

  • 5.8 Semicolons used as statement terminators should be followed by a newline.

  • 5.9 Avoid filler spaces, especially in empty constructs({}, [], function()).

  • 5.10 Assignment operators should have a space on either side.

frame = i;
condition ? expr1 : expr2 
  • 5.12 Logical units within a block should be separated by one blank line.

  • 5.13 There is no hard limit on line length but be reasonable. If you need a number then 80 or 120 characters, including whitespace, are common restrictions.

  • 5.14 Split line positioning for expressions and methods:

var someExpression = Expression1
    + Expression2
    + Expression3
;

var o = someObject.get(
    Expression1,
    Expression2,
    Expression3
);

Comments

  • 6.1 It is often said that good code is its own documentation. This is a wonderful ideal but since we are not the golden gods of coding we'll use comments where applicable.

  • 6.2 Comments should be concise and descriptive. Only write what you need, no more. We aren't going to run out of ink, but if you comment every single line you're an asshole. Prefer writing for readability over commenting on functionality.

  • 6.3 All comments should be written in American English for the sake of uniformity.

  • 6.4 Comments should be indented relative to their position in the code, above the code the describe. Single line comments to the right of the code are also acceptable.

  • 6.5 Collections should be commented describing the common elements.

  • 6.5 Large blocks should be commented.

  • 6.6 Inline comments should be avoided.

  • 6.7 Comments found to be in violation of these rules will be pruned with extreme prejudice.

I don't know how to program

//bad
function sayHi(name) {
  return 'How are you, ' + name + '?';
}

//good
function sayHi(name) {
  return `How are you, ${name}?`;
}
  • 7.2 Always use strict equality checks (===). The only situation where you may use a loose inequality operator (==) is if you are checking for something that could be null or undefined by way of ==null, such as in the case of uninitialized variables.

  • 7.3 You can emulate enums in the style of C by using a single object as a holder for all your constants, naturally in all caps.

var randomEnum {
  ONE_THING: 0,
  ANOTHER_THING: 1,
  THIRD_THING: 2
}
  • 7.4 Singletons are useful for objects that have state.
var pezDispenser = (function() {
  var amount = 20;
  return {
      dispense: function() {
          if (amount > 0) }
              amount -= 1;
              alert('delicious pez!');
          } else {
              alert('no more pez!');
          }
      }
  };
}());

pezDispenser.dispense();

Simply name the function and refrain from invoking it immediately and you have what amounts to a constructor.

  • 7.5 Don't use eval().

  • 7.6 Don't pass strings to setInterval() or setTimeout(). Passing in strings is both painfully slow and potentially insecure. Pass in a function reference instead.